diff --git a/.githooks/pre-commit b/.githooks/pre-commit index f8b6679..c6479f4 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,39 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -# Prevent committing unencrypted secrets in deploy/secrets. -changed_files=$(git diff --cached --name-only --diff-filter=ACMR | rg '^deploy/secrets/.*\.ya?ml$' || true) +ROOT_DIR=$(git rev-parse --show-toplevel) -if [[ -z "${changed_files}" ]]; then - exit 0 -fi - -fail=0 -for file in ${changed_files}; do - if ! rg -q '^sops:' "${file}"; then - echo "ERROR: ${file} is missing sops metadata." >&2 - fail=1 - continue - fi - - # Require encrypted values for secret-like keys. - while IFS= read -r line; do - # Skip comments and empty lines. - [[ "${line}" =~ ^[[:space:]]*# ]] && continue - [[ "${line}" =~ ^[[:space:]]*$ ]] && continue - - # Match KEY: value for secret-like keys. - if [[ "${line}" =~ ^[[:space:]]*([A-Za-z0-9_]*(TOKEN|SECRET|PASSWORD|KEY)[A-Za-z0-9_]*)[[:space:]]*:[[:space:]]*(.+)$ ]]; then - value="${BASH_REMATCH[3]}" - if [[ "${value}" != ENC[* ]]; then - echo "ERROR: ${file} contains unencrypted value for ${BASH_REMATCH[1]}." >&2 - fail=1 - fi - fi - done < "${file}" -done - -if [[ "${fail}" -ne 0 ]]; then - echo "Commit blocked. Encrypt secrets with SOPS before committing." >&2 - exit 1 -fi +"${ROOT_DIR}/scripts/check-sops-secrets.sh" --staged +"${ROOT_DIR}/scripts/check-pii.sh" --staged diff --git a/.github/workflows/pii-check.yml b/.github/workflows/pii-check.yml new file mode 100644 index 0000000..b27f020 --- /dev/null +++ b/.github/workflows/pii-check.yml @@ -0,0 +1,42 @@ +name: PII Check + +on: + push: + branches: + - "**" + pull_request: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + pii-check: + name: Changed files PII check + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Scan changed files for PII and obvious tokens + shell: bash + run: | + set -euo pipefail + chmod +x scripts/check-pii.sh + + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + from_ref="${{ github.event.pull_request.base.sha }}" + to_ref="${{ github.event.pull_request.head.sha }}" + elif [[ -n "${{ github.event.before }}" && "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then + from_ref="${{ github.event.before }}" + to_ref="${{ github.sha }}" + else + from_ref="$(git rev-list --max-parents=0 HEAD)" + to_ref="${{ github.sha }}" + fi + + scripts/check-pii.sh --ref-range "${from_ref}" "${to_ref}" diff --git a/.github/workflows/web-bdd.yml b/.github/workflows/web-bdd.yml index 7269bd6..2258808 100644 --- a/.github/workflows/web-bdd.yml +++ b/.github/workflows/web-bdd.yml @@ -54,8 +54,11 @@ jobs: - name: Run web BDD tests env: + CONTAINER_TOOL: docker + FOSSA_API_TOKEN: dummy-token MD_DB_DRIVER: postgres MD_DB_DSN: host=localhost port=5432 user=maintainerd password=maintainerd dbname=maintainerd_test sslmode=disable + WEB_BDD_USE_MICROCKS: "true" run: make web-bdd - name: Dump web-bdd logs diff --git a/Makefile b/Makefile index 53cc2b7..8a93b21 100644 --- a/Makefile +++ b/Makefile @@ -503,12 +503,15 @@ test-web: TESTDATA_DIR="$${TESTDATA_DIR:-$$(pwd)/testdata}"; \ HOST_LOG_DIR="$${HOST_LOG_DIR:-$$(pwd)/testdata}"; \ mkdir -p "$$TESTDATA_DIR"; \ - bff_pid=""; web_pid=""; \ + bff_pid=""; web_pid=""; microcks_started=""; \ cleanup() { \ status=$$?; \ if [ -n "$$web_pid" ] || [ -n "$$bff_pid" ]; then \ kill $$web_pid $$bff_pid >/dev/null 2>&1 || true; \ fi; \ + if [ -n "$$microcks_started" ]; then \ + CONTAINER_TOOL="$${CONTAINER_TOOL:-podman}" scripts/microcks-down.sh >/dev/null 2>&1 || true; \ + fi; \ if command -v lsof >/dev/null 2>&1; then \ lsof -ti TCP:9001 -ti TCP:4001 2>/dev/null | xargs -r kill >/dev/null 2>&1 || true; \ fi; \ @@ -564,15 +567,27 @@ test-web: echo "MD_DB_DSN is required for test-web."; \ exit 1; \ fi; \ + USE_MICROCKS="$${WEB_BDD_USE_MICROCKS:-false}"; \ + if [ "$$USE_MICROCKS" = "true" ]; then \ + if ! command -v "$${CONTAINER_TOOL:-podman}" >/dev/null 2>&1; then \ + echo "WEB_BDD_USE_MICROCKS=true but container tool $${CONTAINER_TOOL:-podman} is not available."; \ + exit 1; \ + fi; \ + microcks_env="$$(CONTAINER_TOOL="$${CONTAINER_TOOL:-podman}" scripts/microcks-up.sh)"; \ + eval "$$microcks_env"; \ + microcks_started=1; \ + export FOSSA_API_BASE; \ + export FOSSA_API_TOKEN="$${FOSSA_API_TOKEN:-dummy-token}"; \ + fi; \ MD_DB_DRIVER=postgres MD_DB_DSN="$$DB_DSN" go run ./cmd/testdb-reset; \ MD_DB_DRIVER=postgres MD_DB_DSN="$$DB_DSN" go run ./cmd/migrate; \ go run ./cmd/web-bff-seed -driver postgres -dsn "$$DB_DSN"; \ export MD_DB_DRIVER=postgres; \ export MD_DB_DSN="$$DB_DSN"; \ unset MD_DB_PATH; \ - BFF_ADDR=:9001 BFF_TEST_MODE=true BFF_TEST_FOSSA_TEAM_ID=999001 SESSION_COOKIE_SECURE=false SESSION_COOKIE_DOMAIN= \ + BFF_ADDR=:9001 BFF_TEST_MODE=true BFF_ALLOW_LIVE_FOSSA="$$USE_MICROCKS" BFF_TEST_FOSSA_TEAM_ID=999001 SESSION_COOKIE_SECURE=false SESSION_COOKIE_DOMAIN= \ WEB_APP_BASE_URL=http://localhost:4001 GITHUB_OAUTH_REDIRECT_URL=http://localhost:9001/auth/callback \ - GITHUB_OAUTH_CLIENT_ID=test GITHUB_OAUTH_CLIENT_SECRET=test \ + GITHUB_OAUTH_CLIENT_ID=test GITHUB_OAUTH_CLIENT_SECRET=test FOSSA_API_BASE="$${FOSSA_API_BASE:-}" FOSSA_API_TOKEN="$${FOSSA_API_TOKEN:-}" \ go run ./cmd/web-bff > >(tee "$$TESTDATA_DIR/web-bff-test.log") 2>&1 & \ bff_pid=$$!; \ mkdir -p "$$TESTDATA_DIR/tmp" web/tmp || true; \ @@ -584,9 +599,12 @@ test-web: npm --prefix web run start > "$$TESTDATA_DIR/web-app-test.log" 2>&1 & \ web_pid=$$!; \ npx --prefix web wait-on http://localhost:9001/healthz http://localhost:4001 > /dev/null 2>&1; \ - WEB_BASE_URL=http://localhost:4001 BFF_BASE_URL=http://localhost:9001 TEST_STAFF_LOGIN=staff-tester \ - TEST_MAINTAINER_LOGIN=antonio-example TEST_OTHER_MAINTAINER_LOGIN=renee-sample \ - NEXT_TELEMETRY_DISABLED=1 NPM_CONFIG_UPDATE_NOTIFIER=false WEB_TEST_ARTIFACTS_DIR="$$TESTDATA_DIR/web-artifacts" npm --prefix web run test:bdd; \ + BDD_FEATURE_PATH="$${BDD_FEATURE:-}"; \ + if [ -n "$$BDD_FEATURE_PATH" ]; then \ + cd web && WEB_BDD_FEATURE="$$BDD_FEATURE_PATH" WEB_BASE_URL=http://localhost:4001 BFF_BASE_URL=http://localhost:9001 TEST_STAFF_LOGIN=staff-tester TEST_MAINTAINER_LOGIN=antonio-example TEST_OTHER_MAINTAINER_LOGIN=renee-sample NEXT_TELEMETRY_DISABLED=1 NPM_CONFIG_UPDATE_NOTIFIER=false WEB_TEST_ARTIFACTS_DIR="$$TESTDATA_DIR/web-artifacts" npx cucumber-js --config ./cucumber.js; \ + else \ + WEB_BASE_URL=http://localhost:4001 BFF_BASE_URL=http://localhost:9001 TEST_STAFF_LOGIN=staff-tester TEST_MAINTAINER_LOGIN=antonio-example TEST_OTHER_MAINTAINER_LOGIN=renee-sample NEXT_TELEMETRY_DISABLED=1 NPM_CONFIG_UPDATE_NOTIFIER=false WEB_TEST_ARTIFACTS_DIR="$$TESTDATA_DIR/web-artifacts" npm --prefix web run test:bdd; \ + fi; \ ' .PHONY: test-web-license-checker @@ -691,6 +709,15 @@ web-bdd: exit $$status; \ ' +.PHONY: web-bdd-maintainer-profile +web-bdd-maintainer-profile: + @bash -c 'set -euo pipefail; \ + status=0; \ + WEB_BDD_USE_MICROCKS=true BDD_FEATURE=../features/web/maintainer_profile.feature $(MAKE) test-web || status=$$?; \ + $(MAKE) web-bdd-report || true; \ + exit $$status; \ + ' + .PHONY: web-bdd-report web-bdd-report: @bash -c 'set -euo pipefail; \ @@ -1089,6 +1116,7 @@ images-show: @echo " maintainerd-sync $(SYNC_IMAGE)" @echo " maintainerd-sanitize $(SANITIZE_IMAGE)" @echo " maintainerd-migrate $(MIGRATE_IMAGE)" + @echo " maintainerd-fossa-poller $(FOSSA_POLLER_IMAGE)" @echo " maintainerd-web $(WEB_IMAGE)" @echo " maintainerd-web-bff $(WEB_BFF_IMAGE)" diff --git a/README.MD b/README.MD index ed8874b..ed83440 100644 --- a/README.MD +++ b/README.MD @@ -95,5 +95,10 @@ Notes: - `BFF_TEST_MODE=true` enables `/auth/test-login?login=` for local sign-in. - `NEXT_PUBLIC_BFF_BASE_URL` should match the web-bff address. +## Web BDD With Microcks + +For the web BDD test setup that mocks the FOSSA API with Microcks, see +[web/tests/MICROCKS.MD](/home/rk/cncf/gh/maintainer-d/web/tests/MICROCKS.MD). + ## License [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FRobertKielty%2Fmaintainerd.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FRobertKielty%2Fmaintainerd?ref=badge_large) diff --git a/cmd/fossa-poller/main.go b/cmd/fossa-poller/main.go index a2f3a4d..1e17eb8 100644 --- a/cmd/fossa-poller/main.go +++ b/cmd/fossa-poller/main.go @@ -87,6 +87,7 @@ type fossaAPI interface { FetchTeamUserEmails(teamID uint) ([]string, error) FetchTeamMembersRaw(teamID uint) (fossa.TeamMembers, []byte, error) FindUserIDByEmail(email string) (uint, error) + ResolveTeamAdminRoleID() (int, error) } func pollFossaInvites(ctx context.Context, logger *log.Logger, store *db.SQLStore, client fossaAPI) error { @@ -203,8 +204,18 @@ func pollFossaInvites(ctx context.Context, logger *log.Logger, store *db.SQLStor continue } - const fossaTeamAdminRoleID = 3 - addResp, err := client.AddUserToTeamByEmailWithResponse(invite.RemoteTeamID, email, fossaTeamAdminRoleID) + teamAdminRoleID, err := client.ResolveTeamAdminRoleID() + if err != nil { + msg := err.Error() + invite.Status = "error" + invite.LastError = &msg + invite.LastCheckedAt = &now + if _, upsertErr := store.UpsertServiceInvitation(&invite); upsertErr != nil { + logger.Printf("upsert invite failed %s err=%v", formatInviteSummary(store, invite), upsertErr) + } + continue + } + addResp, err := client.AddUserToTeamByEmailWithResponse(invite.RemoteTeamID, email, teamAdminRoleID) if err != nil { if errors.Is(err, fossa.ErrUserAlreadyMember) { invite.Status = "accepted" diff --git a/cmd/fossa-poller/main_test.go b/cmd/fossa-poller/main_test.go index 0bff997..8e40b82 100644 --- a/cmd/fossa-poller/main_test.go +++ b/cmd/fossa-poller/main_test.go @@ -21,6 +21,7 @@ import ( type fakeFossaClient struct { hasPending bool userID uint + roleID int teamEmails []string addResp *fossa.TeamAddResponse addErr error @@ -37,7 +38,7 @@ func (f *fakeFossaClient) AddUserToTeamByEmailWithResponse(uint, string, int) (* if f.addResp != nil || f.addErr != nil { return f.addResp, f.addErr } - return &fossa.TeamAddResponse{Status: "200 OK", Body: []byte(`{"action":"add"}`), UserID: f.userID, RoleID: 3}, nil + return &fossa.TeamAddResponse{Status: "200 OK", Body: []byte(`{"action":"add"}`), UserID: f.userID, RoleID: f.roleID}, nil } func (f *fakeFossaClient) FetchTeamUserEmails(uint) ([]string, error) { return f.teamEmails, nil } func (f *fakeFossaClient) FetchTeamMembersRaw(uint) (fossa.TeamMembers, []byte, error) { @@ -48,6 +49,12 @@ func (f *fakeFossaClient) FetchTeamMembersRaw(uint) (fossa.TeamMembers, []byte, return fossa.TeamMembers{Results: []fossa.TeamMember{{Email: "dana@example.com"}}, TotalCount: 1}, body, nil } func (f *fakeFossaClient) FindUserIDByEmail(string) (uint, error) { return f.userID, nil } +func (f *fakeFossaClient) ResolveTeamAdminRoleID() (int, error) { + if f.roleID == 0 { + return 4, nil + } + return f.roleID, nil +} func setupPollerTestDB(t *testing.T) *gorm.DB { dbConn, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{ diff --git a/cmd/web-bff-seed/main.go b/cmd/web-bff-seed/main.go index ff07b99..d2b4a62 100644 --- a/cmd/web-bff-seed/main.go +++ b/cmd/web-bff-seed/main.go @@ -211,6 +211,8 @@ func main() { log.Fatalf("seed: association failed: %v", err) } if err := dbConn.Model(projectMap["Project Fossa Partial"]).Association("Maintainers").Replace( + &maintainers[0], + &maintainers[1], &maintainers[2], &maintainers[3], ); err != nil { @@ -273,7 +275,7 @@ func main() { remoteUsers := []model.RemoteUser{ {ServiceID: fossa.ID, RemoteUserID: 1, ServiceEmail: maintainers[0].Email}, - {ServiceID: fossa.ID, RemoteUserID: 2, ServiceEmail: maintainers[1].Email}, + {ServiceID: fossa.ID, RemoteUserID: 2, ServiceEmail: maintainers[1].GitHubEmail}, {ServiceID: fossa.ID, RemoteUserID: 3, ServiceEmail: maintainers[2].Email}, {ServiceID: fossa.ID, RemoteUserID: 4, ServiceEmail: maintainers[5].Email}, } @@ -286,7 +288,6 @@ func main() { serviceUserTeams := []model.RemoteTeamUser{ {ServiceID: fossa.ID, TeamID: teams[0].ID, UserID: remoteUsers[0].ID, MaintainerID: &maintainers[0].ID}, {ServiceID: fossa.ID, TeamID: teams[0].ID, UserID: remoteUsers[1].ID, MaintainerID: &maintainers[1].ID}, - {ServiceID: fossa.ID, TeamID: teams[1].ID, UserID: remoteUsers[2].ID, MaintainerID: &maintainers[2].ID}, {ServiceID: fossa.ID, TeamID: teams[2].ID, UserID: remoteUsers[3].ID, MaintainerID: &maintainers[5].ID}, } for i := range serviceUserTeams { diff --git a/cmd/web-bff/main.go b/cmd/web-bff/main.go index 98c44bf..59f1c8e 100644 --- a/cmd/web-bff/main.go +++ b/cmd/web-bff/main.go @@ -1732,6 +1732,7 @@ type maintainerDetailResponse struct { CompanyID *uint `json:"companyId,omitempty"` Company string `json:"company,omitempty"` Projects []maintainerProjectResponse `json:"projects"` + Services []maintainerServiceResponse `json:"services,omitempty"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt,omitempty"` @@ -1743,6 +1744,38 @@ type maintainerProjectResponse struct { Name string `json:"name"` } +type maintainerServiceResponse struct { + Kind string `json:"kind"` + Label string `json:"label"` + Account maintainerServiceAccountResponse `json:"account"` + Targets []maintainerServiceTargetResponse `json:"targets"` +} + +type maintainerServiceAccountResponse struct { + State string `json:"state"` + MatchedBy string `json:"matchedBy"` + RemoteUserID *uint `json:"remoteUserId,omitempty"` + RemoteRef string `json:"remoteRef,omitempty"` + EmailUsed string `json:"emailUsed,omitempty"` + LastCheckedAt *time.Time `json:"lastCheckedAt,omitempty"` + PendingInvitations int `json:"pendingInvitations,omitempty"` + AcceptedInvitations int `json:"acceptedInvitations,omitempty"` + Error string `json:"error,omitempty"` +} + +type maintainerServiceTargetResponse struct { + ProjectID uint `json:"projectId"` + ProjectName string `json:"projectName"` + TargetKind string `json:"targetKind"` + TargetID *uint `json:"targetId,omitempty"` + TargetName string `json:"targetName"` + Required bool `json:"required"` + State string `json:"state"` + PendingInvite bool `json:"pendingInvite,omitempty"` + LastCheckedAt *time.Time `json:"lastCheckedAt,omitempty"` + Error string `json:"error,omitempty"` +} + type auditLogResponse struct { ID uint `json:"id"` Action string `json:"action"` @@ -1767,6 +1800,10 @@ func (s *server) handleMaintainer(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) return } + if maintainerID, serviceKind, action, ok := parseMaintainerServiceActionPath(r.URL.Path); ok { + s.handleMaintainerServiceAction(w, r, maintainerID, serviceKind, action) + return + } id, err := parseIDParam(r.URL.Path, "/api/maintainers/") if err != nil { http.Error(w, "invalid maintainer id", http.StatusBadRequest) @@ -1797,35 +1834,14 @@ func (s *server) handleMaintainer(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - var maintainer model.Maintainer - if err := s.store.DB(). - Preload("Company"). - Preload("Projects"). - First(&maintainer, id).Error; err != nil { + maintainer, err := s.loadMaintainerWithRelations(id) + if err != nil { s.logger.Printf("web-bff: maintainer not found id=%d path=%s user=%s role=%s err=%v", id, r.URL.Path, login, role, err) http.Error(w, "maintainer not found", http.StatusNotFound) return } - projects := make([]maintainerProjectResponse, 0, len(maintainer.Projects)) - for _, project := range maintainer.Projects { - projects = append(projects, maintainerProjectResponse{ - ID: project.ID, - Name: project.Name, - }) - } - - response := maintainerDetailResponse{ - ID: maintainer.ID, - Name: maintainer.Name, - Email: normalizeValue(maintainer.Email, "EMAIL_MISSING"), - GitHub: normalizeValue(maintainer.GitHubAccount, "GITHUB_MISSING"), - GitHubEmail: normalizeValue(maintainer.GitHubEmail, "GITHUB_MISSING"), - Status: string(maintainer.MaintainerStatus), - Projects: projects, - CreatedAt: maintainer.CreatedAt, - UpdatedAt: maintainer.UpdatedAt, - } + response := s.buildMaintainerDetailResponse(*maintainer, session.Role == roleStaff) if maintainer.DeletedAt.Valid { deleted := maintainer.DeletedAt.Time response.DeletedAt = &deleted @@ -2053,6 +2069,817 @@ func (s *server) handleMaintainer(w http.ResponseWriter, r *http.Request) { } } +func (s *server) buildMaintainerServices(maintainer model.Maintainer) []maintainerServiceResponse { + services := make([]maintainerServiceResponse, 0, 1) + + fossaService, ok := s.buildMaintainerFossaService(maintainer) + if ok { + services = append(services, fossaService) + } + + return services +} + +func (s *server) loadMaintainerWithRelations(id uint) (*model.Maintainer, error) { + var maintainer model.Maintainer + if err := s.store.DB(). + Preload("Company"). + Preload("Projects"). + First(&maintainer, id).Error; err != nil { + return nil, err + } + return &maintainer, nil +} + +func (s *server) buildMaintainerDetailResponse(maintainer model.Maintainer, includeServices bool) maintainerDetailResponse { + projects := make([]maintainerProjectResponse, 0, len(maintainer.Projects)) + for _, project := range maintainer.Projects { + projects = append(projects, maintainerProjectResponse{ + ID: project.ID, + Name: project.Name, + }) + } + + response := maintainerDetailResponse{ + ID: maintainer.ID, + Name: maintainer.Name, + Email: normalizeValue(maintainer.Email, "EMAIL_MISSING"), + GitHub: normalizeValue(maintainer.GitHubAccount, "GITHUB_MISSING"), + GitHubEmail: normalizeValue(maintainer.GitHubEmail, "GITHUB_MISSING"), + Status: string(maintainer.MaintainerStatus), + Projects: projects, + CreatedAt: maintainer.CreatedAt, + UpdatedAt: maintainer.UpdatedAt, + } + if includeServices { + response.Services = s.buildMaintainerServices(maintainer) + } + if maintainer.DeletedAt.Valid { + deleted := maintainer.DeletedAt.Time + response.DeletedAt = &deleted + } + if maintainer.CompanyID != nil { + response.CompanyID = maintainer.CompanyID + } + if maintainer.Company.Name != "" { + response.Company = maintainer.Company.Name + } + return response +} + +func (s *server) buildMaintainerFossaService(maintainer model.Maintainer) (maintainerServiceResponse, bool) { + serviceID, err := s.getFossaServiceID() + if err != nil { + return maintainerServiceResponse{}, false + } + + projects, err := s.loadMaintainerServiceProjects(maintainer.ID, serviceID) + if err != nil || len(projects) == 0 { + return maintainerServiceResponse{}, false + } + + projectIDs := make([]uint, 0, len(projects)) + for _, project := range projects { + projectIDs = append(projectIDs, project.ID) + } + + var remoteTeams []model.RemoteTeam + if err := s.store.DB(). + Where("service_id = ? AND project_id IN ?", serviceID, projectIDs). + Find(&remoteTeams).Error; err != nil { + return maintainerServiceResponse{}, false + } + + teamByProjectID := make(map[uint]model.RemoteTeam, len(remoteTeams)) + teamIDs := make([]uint, 0, len(remoteTeams)) + for _, team := range remoteTeams { + teamByProjectID[team.ProjectID] = team + teamIDs = append(teamIDs, team.ID) + } + + candidateEmails := maintainerServiceCandidateEmails(maintainer) + + remoteUsers := make([]model.RemoteUser, 0) + if len(candidateEmails) > 0 { + if err := s.store.DB(). + Where("service_id = ? AND LOWER(service_email) IN ?", serviceID, candidateEmails). + Find(&remoteUsers).Error; err != nil { + return maintainerServiceResponse{}, false + } + } + + var invites []model.ServiceInvitation + inviteQuery := s.store.DB(). + Where("service_id = ? AND project_id IN ?", serviceID, projectIDs). + Where("maintainer_id = ?", maintainer.ID) + if len(candidateEmails) > 0 { + inviteQuery = inviteQuery.Or( + "service_id = ? AND project_id IN ? AND LOWER(service_email) IN ?", + serviceID, + projectIDs, + candidateEmails, + ) + } + if err := inviteQuery.Order("created_at desc").Find(&invites).Error; err != nil { + return maintainerServiceResponse{}, false + } + + membershipQuery := s.store.DB().Where("service_id = ?", serviceID) + if len(teamIDs) > 0 { + membershipQuery = membershipQuery.Where("team_id IN ?", teamIDs) + } + + remoteUserIDs := make([]uint, 0, len(remoteUsers)) + for _, user := range remoteUsers { + remoteUserIDs = append(remoteUserIDs, user.ID) + } + if len(remoteUserIDs) > 0 { + membershipQuery = membershipQuery.Where("maintainer_id = ? OR user_id IN ?", maintainer.ID, remoteUserIDs) + } else { + membershipQuery = membershipQuery.Where("maintainer_id = ?", maintainer.ID) + } + + var memberships []model.RemoteTeamUser + if err := membershipQuery.Find(&memberships).Error; err != nil { + return maintainerServiceResponse{}, false + } + + selectedRemoteUser, matchedBy := selectMaintainerRemoteUser(maintainer, remoteUsers) + account := buildMaintainerServiceAccount(selectedRemoteUser, matchedBy, invites) + targets := buildMaintainerServiceTargets(projects, teamByProjectID, memberships, invites, account.State) + + return maintainerServiceResponse{ + Kind: "fossa", + Label: "CNCF FOSSA", + Account: account, + Targets: targets, + }, true +} + +func (s *server) loadMaintainerServiceProjects(maintainerID, serviceID uint) ([]model.Project, error) { + var projects []model.Project + err := s.store.DB(). + Model(&model.Project{}). + Distinct("projects.*"). + Joins("JOIN maintainer_projects mp ON mp.project_id = projects.id"). + Joins("JOIN service_projects sp ON sp.project_id = projects.id"). + Where("mp.maintainer_id = ? AND sp.service_id = ?", maintainerID, serviceID). + Order("projects.name asc"). + Find(&projects).Error + return projects, err +} + +func maintainerServiceCandidateEmails(maintainer model.Maintainer) []string { + values := []string{ + strings.ToLower(strings.TrimSpace(maintainer.Email)), + strings.ToLower(strings.TrimSpace(maintainer.GitHubEmail)), + } + seen := make(map[string]struct{}, len(values)) + candidateEmails := make([]string, 0, len(values)) + for _, value := range values { + if value == "" || value == "email_missing" || value == "github_email_missing" || value == "github_missing" { + continue + } + if _, ok := seen[value]; ok { + continue + } + seen[value] = struct{}{} + candidateEmails = append(candidateEmails, value) + } + return candidateEmails +} + +func selectMaintainerRemoteUser(maintainer model.Maintainer, remoteUsers []model.RemoteUser) (*model.RemoteUser, string) { + maintainerEmail := strings.ToLower(strings.TrimSpace(maintainer.Email)) + githubEmail := strings.ToLower(strings.TrimSpace(maintainer.GitHubEmail)) + + for i := range remoteUsers { + email := strings.ToLower(strings.TrimSpace(remoteUsers[i].ServiceEmail)) + if maintainerEmail != "" && email == maintainerEmail { + return &remoteUsers[i], "maintainer_email" + } + } + for i := range remoteUsers { + email := strings.ToLower(strings.TrimSpace(remoteUsers[i].ServiceEmail)) + if githubEmail != "" && email == githubEmail { + return &remoteUsers[i], "github_email" + } + } + if len(remoteUsers) > 0 { + return &remoteUsers[0], "unknown" + } + return nil, "none" +} + +func buildMaintainerServiceAccount(selectedRemoteUser *model.RemoteUser, matchedBy string, invites []model.ServiceInvitation) maintainerServiceAccountResponse { + account := maintainerServiceAccountResponse{ + State: "unknown", + MatchedBy: matchedBy, + } + + var latestCheckedAt *time.Time + pendingInvites := 0 + acceptedInvites := 0 + lastError := "" + for _, invite := range invites { + if invite.LastCheckedAt != nil && (latestCheckedAt == nil || invite.LastCheckedAt.After(*latestCheckedAt)) { + latestCheckedAt = invite.LastCheckedAt + } + switch strings.ToLower(strings.TrimSpace(invite.Status)) { + case "pending", "expired": + pendingInvites++ + case "accepted": + acceptedInvites++ + case "error": + if invite.LastError != nil && strings.TrimSpace(*invite.LastError) != "" { + lastError = strings.TrimSpace(*invite.LastError) + } + } + } + account.LastCheckedAt = latestCheckedAt + account.PendingInvitations = pendingInvites + account.AcceptedInvitations = acceptedInvites + + if selectedRemoteUser != nil { + account.State = "registered" + account.RemoteUserID = &selectedRemoteUser.RemoteUserID + account.RemoteRef = strings.TrimSpace(selectedRemoteUser.RemoteRef) + account.EmailUsed = strings.TrimSpace(selectedRemoteUser.ServiceEmail) + return account + } + if pendingInvites > 0 { + account.State = "invited" + if len(invites) > 0 { + account.EmailUsed = strings.TrimSpace(invites[0].ServiceEmail) + } + return account + } + if acceptedInvites > 0 { + account.State = "registered" + if len(invites) > 0 { + account.EmailUsed = strings.TrimSpace(invites[0].ServiceEmail) + } + return account + } + if lastError != "" { + account.State = "error" + account.Error = lastError + return account + } + + account.State = "not_registered" + return account +} + +func buildMaintainerServiceTargets( + projects []model.Project, + teamByProjectID map[uint]model.RemoteTeam, + memberships []model.RemoteTeamUser, + invites []model.ServiceInvitation, + accountState string, +) []maintainerServiceTargetResponse { + membershipByTeamID := make(map[uint]model.RemoteTeamUser, len(memberships)) + for _, membership := range memberships { + if _, exists := membershipByTeamID[membership.TeamID]; !exists { + membershipByTeamID[membership.TeamID] = membership + } + } + + inviteByProjectID := make(map[uint]model.ServiceInvitation, len(invites)) + for _, invite := range invites { + if _, exists := inviteByProjectID[invite.ProjectID]; !exists { + inviteByProjectID[invite.ProjectID] = invite + } + } + + targets := make([]maintainerServiceTargetResponse, 0, len(projects)) + for _, project := range projects { + target := maintainerServiceTargetResponse{ + ProjectID: project.ID, + ProjectName: project.Name, + TargetKind: "team", + Required: true, + State: "missing", + } + + team, hasTeam := teamByProjectID[project.ID] + invite, hasInvite := inviteByProjectID[project.ID] + if hasInvite { + target.LastCheckedAt = invite.LastCheckedAt + } + + if !hasTeam { + target.TargetName = "FOSSA team not assigned" + target.State = "error" + target.Error = "Project does not have a cached FOSSA team" + targets = append(targets, target) + continue + } + + target.TargetID = &team.RemoteTeamID + if team.RemoteTeamName != nil && strings.TrimSpace(*team.RemoteTeamName) != "" { + target.TargetName = strings.TrimSpace(*team.RemoteTeamName) + } else { + target.TargetName = fmt.Sprintf("Team %d", team.RemoteTeamID) + } + + if _, ok := membershipByTeamID[team.ID]; ok { + target.State = "member" + targets = append(targets, target) + continue + } + + if hasInvite { + switch strings.ToLower(strings.TrimSpace(invite.Status)) { + case "pending", "expired": + target.State = "pending" + target.PendingInvite = true + case "error": + target.State = "error" + if invite.LastError != nil { + target.Error = strings.TrimSpace(*invite.LastError) + } + case "accepted": + if invite.TeamAssignmentStatus != nil && strings.EqualFold(strings.TrimSpace(*invite.TeamAssignmentStatus), "error") { + target.State = "error" + if invite.LastError != nil { + target.Error = strings.TrimSpace(*invite.LastError) + } + } else if invite.TeamAssignmentStatus != nil && strings.EqualFold(strings.TrimSpace(*invite.TeamAssignmentStatus), "done") { + target.State = "member" + } else { + target.State = "pending" + } + default: + if accountState == "registered" { + target.State = "missing" + } + } + targets = append(targets, target) + continue + } + + switch accountState { + case "registered": + target.State = "missing" + case "invited": + target.State = "pending" + target.PendingInvite = true + case "not_registered": + target.State = "missing" + } + + targets = append(targets, target) + } + + return targets +} + +func (s *server) handleMaintainerServiceAction(w http.ResponseWriter, r *http.Request, maintainerID uint, serviceKind, action string) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + session := sessionFromContext(r.Context()) + if session == nil || session.Role != roleStaff { + http.Error(w, "forbidden", http.StatusForbidden) + return + } + + maintainer, err := s.loadMaintainerWithRelations(maintainerID) + if err != nil { + http.Error(w, "maintainer not found", http.StatusNotFound) + return + } + + switch serviceKind { + case "fossa": + switch action { + case "refresh": + err = s.refreshMaintainerFossaState(*maintainer) + case "invite": + err = s.inviteMaintainerToFossa(*maintainer) + case "reconcile": + err = s.reconcileMaintainerFossaTeams(*maintainer) + default: + http.Error(w, "not found", http.StatusNotFound) + return + } + default: + http.Error(w, "not found", http.StatusNotFound) + return + } + + if err != nil { + s.logger.Printf("web-bff: maintainer service action failed maintainer=%d service=%s action=%s err=%v", maintainerID, serviceKind, action, err) + http.Error(w, err.Error(), http.StatusBadGateway) + return + } + + updatedMaintainer, err := s.loadMaintainerWithRelations(maintainerID) + if err != nil { + http.Error(w, "maintainer not found", http.StatusNotFound) + return + } + response := s.buildMaintainerDetailResponse(*updatedMaintainer, true) + w.Header().Set(headerContentType, contentTypeJSON) + if err := json.NewEncoder(w).Encode(response); err != nil { + s.logger.Printf("web-bff: handleMaintainerServiceAction encode error: %v", err) + } +} + +func (s *server) refreshMaintainerFossaState(maintainer model.Maintainer) error { + serviceID, projects, serviceTeams, client, err := s.loadMaintainerFossaContext(maintainer, false) + if err != nil { + return err + } + + now := time.Now().UTC() + users, err := client.FetchUsers() + if err != nil { + return err + } + matchedUser, emailUsed := findFossaUserForMaintainer(users, maintainer) + + var remoteUser *model.RemoteUser + if matchedUser != nil { + remoteUser, err = s.upsertFossaRemoteUser(serviceID, *matchedUser, emailUsed) + if err != nil { + return err + } + for _, serviceTeam := range serviceTeams { + if fossaUserHasTeam(*matchedUser, serviceTeam.RemoteTeamID) { + if err := s.upsertFossaMembership(serviceID, *serviceTeam, remoteUser, maintainer.ID); err != nil { + return err + } + } + } + } + + pendingEmails, err := client.FetchUserInvitationEmails() + if err != nil { + return err + } + pendingByEmail := normalizeEmailSet(pendingEmails) + + candidateEmails := maintainerServiceCandidateEmails(maintainer) + var invites []model.ServiceInvitation + if err := s.store.DB(). + Where("service_id = ? AND maintainer_id = ? AND project_id IN ?", serviceID, maintainer.ID, projectIDsForProjects(projects)). + Order("created_at desc"). + Find(&invites).Error; err != nil { + return err + } + inviteByProjectID := make(map[uint]model.ServiceInvitation, len(invites)) + for _, invite := range invites { + if _, ok := inviteByProjectID[invite.ProjectID]; !ok { + inviteByProjectID[invite.ProjectID] = invite + } + } + + for _, project := range projects { + serviceTeam := serviceTeams[project.ID] + invite, hasInvite := inviteByProjectID[project.ID] + pendingEmail := firstMatchingPendingEmail(candidateEmails, pendingByEmail) + hasMembership := matchedUser != nil && fossaUserHasTeam(*matchedUser, serviceTeam.RemoteTeamID) + switch { + case pendingEmail != "": + if !hasInvite { + invite = model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + } + } + invite.ServiceEmail = pendingEmail + invite.RemoteTeamID = serviceTeam.RemoteTeamID + invite.Status = "pending" + invite.LastError = nil + invite.LastCheckedAt = &now + if _, err := s.store.UpsertServiceInvitation(&invite); err != nil { + return err + } + case matchedUser != nil: + if hasInvite { + invite.ServiceEmail = firstNonEmpty(emailUsed, invite.ServiceEmail) + invite.RemoteTeamID = serviceTeam.RemoteTeamID + invite.Status = "accepted" + invite.LastError = nil + invite.LastCheckedAt = &now + if hasMembership { + done := "done" + invite.TeamAssignmentStatus = &done + } else { + pending := "pending" + invite.TeamAssignmentStatus = &pending + } + if _, err := s.store.UpsertServiceInvitation(&invite); err != nil { + return err + } + } + case hasInvite: + invite.Status = "expired" + invite.LastCheckedAt = &now + if _, err := s.store.UpsertServiceInvitation(&invite); err != nil { + return err + } + } + } + + return nil +} + +func (s *server) inviteMaintainerToFossa(maintainer model.Maintainer) error { + serviceID, projects, serviceTeams, client, err := s.loadMaintainerFossaContext(maintainer, true) + if err != nil { + return err + } + + email := preferredMaintainerServiceEmail(maintainer) + if email == "" { + return fmt.Errorf("maintainer is missing an email address") + } + + now := time.Now().UTC() + err = client.SendUserInvitation(email) + if err == nil || errors.Is(err, fossa.ErrInviteAlreadyExists) { + for _, project := range projects { + serviceTeam := serviceTeams[project.ID] + invite := &model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + ServiceEmail: email, + RemoteTeamID: serviceTeam.RemoteTeamID, + Status: "pending", + SentAt: &now, + LastCheckedAt: &now, + LastError: nil, + } + if _, upsertErr := s.store.UpsertServiceInvitation(invite); upsertErr != nil { + return upsertErr + } + } + return nil + } + if errors.Is(err, fossa.ErrUserAlreadyMember) { + return s.reconcileMaintainerFossaTeams(maintainer) + } + + msg := err.Error() + for _, project := range projects { + serviceTeam := serviceTeams[project.ID] + invite := &model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + ServiceEmail: email, + RemoteTeamID: serviceTeam.RemoteTeamID, + Status: "error", + LastCheckedAt: &now, + LastError: &msg, + } + if _, upsertErr := s.store.UpsertServiceInvitation(invite); upsertErr != nil { + return upsertErr + } + } + return err +} + +func (s *server) reconcileMaintainerFossaTeams(maintainer model.Maintainer) error { + serviceID, projects, serviceTeams, client, err := s.loadMaintainerFossaContext(maintainer, true) + if err != nil { + return err + } + + users, err := client.FetchUsers() + if err != nil { + return err + } + matchedUser, emailUsed := findFossaUserForMaintainer(users, maintainer) + if matchedUser == nil { + return fmt.Errorf("maintainer is not registered with CNCF FOSSA") + } + + remoteUser, err := s.upsertFossaRemoteUser(serviceID, *matchedUser, emailUsed) + if err != nil { + return err + } + + now := time.Now().UTC() + for _, project := range projects { + serviceTeam := serviceTeams[project.ID] + if !fossaUserHasTeam(*matchedUser, serviceTeam.RemoteTeamID) { + teamAdminRoleID, err := client.ResolveTeamAdminRoleID() + if err != nil { + return err + } + if err := client.AddUserToTeamByEmail(serviceTeam.RemoteTeamID, emailUsed, teamAdminRoleID); err != nil && !errors.Is(err, fossa.ErrUserAlreadyMember) { + msg := err.Error() + invite := &model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + ServiceEmail: emailUsed, + RemoteTeamID: serviceTeam.RemoteTeamID, + Status: "error", + LastCheckedAt: &now, + LastError: &msg, + } + if _, upsertErr := s.store.UpsertServiceInvitation(invite); upsertErr != nil { + return upsertErr + } + return err + } + } + if err := s.upsertFossaMembership(serviceID, *serviceTeam, remoteUser, maintainer.ID); err != nil { + return err + } + done := "done" + invite := &model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + ServiceEmail: emailUsed, + RemoteTeamID: serviceTeam.RemoteTeamID, + Status: "accepted", + TeamAssignmentStatus: &done, + TeamAddAttempts: 1, + LastCheckedAt: &now, + LastError: nil, + } + if _, upsertErr := s.store.UpsertServiceInvitation(invite); upsertErr != nil { + return upsertErr + } + } + + return nil +} + +func (s *server) loadMaintainerFossaContext(maintainer model.Maintainer, ensureTeams bool) (uint, []model.Project, map[uint]*model.RemoteTeam, *fossa.Client, error) { + serviceID, err := s.getFossaServiceID() + if err != nil { + return 0, nil, nil, nil, err + } + + projects, err := s.loadMaintainerServiceProjects(maintainer.ID, serviceID) + if err != nil { + return 0, nil, nil, nil, err + } + if len(projects) == 0 { + return 0, nil, nil, nil, fmt.Errorf("maintainer has no FOSSA-enabled projects") + } + + client, err := s.fossaClient() + if err != nil { + return 0, nil, nil, nil, err + } + + serviceTeams := make(map[uint]*model.RemoteTeam, len(projects)) + for _, project := range projects { + serviceTeam, err := s.store.GetRemoteTeamByProject(project.ID, serviceID) + if err != nil { + return 0, nil, nil, nil, err + } + if serviceTeam == nil && ensureTeams { + serviceTeam, _, err = s.ensureFossaTeam(project, client) + if err != nil { + return 0, nil, nil, nil, err + } + } + if serviceTeam == nil { + return 0, nil, nil, nil, fmt.Errorf("project %s does not have a cached FOSSA team", project.Name) + } + serviceTeams[project.ID] = serviceTeam + } + + return serviceID, projects, serviceTeams, client, nil +} + +func (s *server) upsertFossaRemoteUser(serviceID uint, user fossa.User, emailUsed string) (*model.RemoteUser, error) { + serviceEmail := strings.TrimSpace(user.Email) + if serviceEmail == "" { + serviceEmail = emailUsed + } + var githubName *string + if user.GitHub.Name != nil && strings.TrimSpace(*user.GitHub.Name) != "" { + value := strings.TrimSpace(*user.GitHub.Name) + githubName = &value + } + return s.store.UpsertRemoteUser(&model.RemoteUser{ + ServiceID: serviceID, + RemoteUserID: user.ID, + ServiceEmail: serviceEmail, + RemoteRef: strings.TrimSpace(user.Username), + ServiceGitHubName: githubName, + }) +} + +func (s *server) upsertFossaMembership(serviceID uint, serviceTeam model.RemoteTeam, remoteUser *model.RemoteUser, maintainerID uint) error { + if remoteUser == nil { + return fmt.Errorf("missing remote user") + } + link := &model.RemoteTeamUser{ + ServiceID: serviceID, + TeamID: serviceTeam.ID, + UserID: remoteUser.ID, + MaintainerID: &maintainerID, + } + _, err := s.store.UpsertRemoteUserTeam(link) + return err +} + +func normalizeEmailSet(values map[string]struct{}) map[string]struct{} { + normalized := make(map[string]struct{}, len(values)) + for value := range values { + email := strings.ToLower(strings.TrimSpace(value)) + if email == "" { + continue + } + normalized[email] = struct{}{} + } + return normalized +} + +func firstMatchingPendingEmail(candidateEmails []string, pendingByEmail map[string]struct{}) string { + for _, email := range candidateEmails { + if _, ok := pendingByEmail[email]; ok { + return email + } + } + return "" +} + +func preferredMaintainerServiceEmail(maintainer model.Maintainer) string { + if email := strings.TrimSpace(normalizeValue(maintainer.Email, "EMAIL_MISSING")); email != "" { + return email + } + if email := strings.TrimSpace(normalizeValue(maintainer.GitHubEmail, "GITHUB_MISSING")); email != "" { + return email + } + return "" +} + +func firstNonEmpty(values ...string) string { + for _, value := range values { + if strings.TrimSpace(value) != "" { + return strings.TrimSpace(value) + } + } + return "" +} + +func projectIDsForProjects(projects []model.Project) []uint { + projectIDs := make([]uint, 0, len(projects)) + for _, project := range projects { + projectIDs = append(projectIDs, project.ID) + } + return projectIDs +} + +func findFossaUserForMaintainer(users []fossa.User, maintainer model.Maintainer) (*fossa.User, string) { + candidateEmails := maintainerServiceCandidateEmails(maintainer) + if len(candidateEmails) == 0 { + return nil, "" + } + + for _, candidate := range candidateEmails { + for i := range users { + if fossaUserMatchesEmail(users[i], candidate) { + return &users[i], candidate + } + } + } + + return nil, "" +} + +func fossaUserMatchesEmail(user fossa.User, email string) bool { + normalized := strings.ToLower(strings.TrimSpace(email)) + if normalized == "" { + return false + } + if strings.EqualFold(strings.TrimSpace(user.Email), normalized) { + return true + } + if user.GitHub.Email != nil && strings.EqualFold(strings.TrimSpace(*user.GitHub.Email), normalized) { + return true + } + if user.Bitbucket.Email != nil && strings.EqualFold(strings.TrimSpace(*user.Bitbucket.Email), normalized) { + return true + } + return false +} + +func fossaUserHasTeam(user fossa.User, remoteTeamID uint) bool { + for _, membership := range user.TeamUsers { + if membership.Team.ID == remoteTeamID { + return true + } + } + return false +} + func (s *server) handleAudit(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) @@ -3447,8 +4274,27 @@ func (s *server) handleFossaInvite(w http.ResponseWriter, r *http.Request) { } if errors.Is(err, fossa.ErrUserAlreadyMember) { - const fossaTeamAdminRoleID = 3 - if addErr := client.AddUserToTeamByEmail(serviceTeam.RemoteTeamID, email, fossaTeamAdminRoleID); addErr == nil { + teamAdminRoleID, resolveErr := client.ResolveTeamAdminRoleID() + if resolveErr != nil { + msg := resolveErr.Error() + inviteStatus := &model.ServiceInvitation{ + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceID: serviceID, + ServiceEmail: email, + RemoteTeamID: serviceTeam.RemoteTeamID, + Status: "error", + LastError: &msg, + LastCheckedAt: &now, + } + if _, upsertErr := s.store.UpsertServiceInvitation(inviteStatus); upsertErr != nil { + resp.Errors[email] = "failed to store invite status" + } else { + resp.Errors[email] = msg + } + continue + } + if addErr := client.AddUserToTeamByEmail(serviceTeam.RemoteTeamID, email, teamAdminRoleID); addErr == nil { inviteStatus := &model.ServiceInvitation{ ProjectID: project.ID, MaintainerID: &maintainer.ID, @@ -3912,8 +4758,19 @@ func (s *server) handleFossaInviteAction(w http.ResponseWriter, r *http.Request) return } if errors.Is(err, fossa.ErrUserAlreadyMember) { - const fossaTeamAdminRoleID = 3 - if addErr := client.AddUserToTeamByEmail(invite.RemoteTeamID, email, fossaTeamAdminRoleID); addErr == nil { + teamAdminRoleID, resolveErr := client.ResolveTeamAdminRoleID() + if resolveErr != nil { + msg := resolveErr.Error() + invite.Status = "error" + invite.LastError = &msg + invite.LastCheckedAt = &now + if _, upsertErr := s.store.UpsertServiceInvitation(invite); upsertErr != nil { + s.logger.Printf("web-bff: handleFossaInviteAction upsert error: %v", upsertErr) + } + http.Error(w, msg, http.StatusBadGateway) + return + } + if addErr := client.AddUserToTeamByEmail(invite.RemoteTeamID, email, teamAdminRoleID); addErr == nil { invite.Status = "accepted" invite.LastError = nil invite.LastCheckedAt = &now @@ -4600,6 +5457,19 @@ func parseCSVParam(r *http.Request, key string) []string { return out } +func parseMaintainerServiceActionPath(path string) (uint, string, string, bool) { + trimmed := strings.Trim(strings.TrimPrefix(path, "/api/maintainers/"), "/") + parts := strings.Split(trimmed, "/") + if len(parts) != 4 || parts[1] != "services" { + return 0, "", "", false + } + id, err := strconv.Atoi(parts[0]) + if err != nil || id <= 0 { + return 0, "", "", false + } + return uint(id), parts[2], parts[3], true +} + func parseIDParam(path, prefix string) (uint, error) { trimmed := strings.TrimPrefix(path, prefix) trimmed = strings.Trim(trimmed, "/") diff --git a/cmd/web-bff/main_test.go b/cmd/web-bff/main_test.go index 8d2d25f..689bf46 100644 --- a/cmd/web-bff/main_test.go +++ b/cmd/web-bff/main_test.go @@ -104,6 +104,16 @@ func performMaintainerGet(t *testing.T, s *server, maintainerID uint, sessionID return rec } +func performMaintainerAction(t *testing.T, s *server, maintainerID uint, action string, sessionID string) *httptest.ResponseRecorder { + t.Helper() + req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/maintainers/%d/services/fossa/%s", maintainerID, action), nil) + req.AddCookie(&http.Cookie{Name: s.cookieName, Value: sessionID}) + rec := httptest.NewRecorder() + handler := s.requireSession(http.HandlerFunc(s.handleMaintainer)) + handler.ServeHTTP(rec, req) + return rec +} + func TestMaintainerEmailRedaction(t *testing.T) { dbConn := setupPostgresTestDB(t) store := db.NewSQLStore(dbConn) @@ -271,6 +281,458 @@ func TestMaintainerCanAccessAllProjectsAndMaintainers(t *testing.T) { }) } +func TestMaintainerServiceAssociationsForStaff(t *testing.T) { + dbConn := setupPostgresTestDB(t) + store := db.NewSQLStore(dbConn) + now := time.Now() + + staff := model.StaffMember{ + Name: "Staff Tester", + GitHubAccount: "staff-tester", + Email: "staff@example.org", + } + require.NoError(t, dbConn.Create(&staff).Error) + + fossa := model.Service{Name: "FOSSA", Description: "License compliance"} + require.NoError(t, dbConn.Create(&fossa).Error) + + maintainer := model.Maintainer{ + Name: "Alice Example", + Email: "alice@example.org", + GitHubAccount: "alice-example", + GitHubEmail: "alice@github.example", + MaintainerStatus: model.ActiveMaintainer, + } + require.NoError(t, dbConn.Create(&maintainer).Error) + + projectA := model.Project{Name: "Project A", Maturity: model.Sandbox} + projectB := model.Project{Name: "Project B", Maturity: model.Graduated} + require.NoError(t, dbConn.Create(&projectA).Error) + require.NoError(t, dbConn.Create(&projectB).Error) + require.NoError(t, dbConn.Model(&projectA).Association("Maintainers").Append(&maintainer)) + require.NoError(t, dbConn.Model(&projectB).Association("Maintainers").Append(&maintainer)) + require.NoError(t, dbConn.Model(&projectA).Association("Services").Append(&fossa)) + require.NoError(t, dbConn.Model(&projectB).Association("Services").Append(&fossa)) + + teamAName := "Project A Team" + teamBName := "Project B Team" + teamA := model.RemoteTeam{ + ProjectID: projectA.ID, + ServiceID: fossa.ID, + RemoteTeamID: 101, + RemoteTeamName: &teamAName, + ProjectName: &projectA.Name, + } + teamB := model.RemoteTeam{ + ProjectID: projectB.ID, + ServiceID: fossa.ID, + RemoteTeamID: 102, + RemoteTeamName: &teamBName, + ProjectName: &projectB.Name, + } + require.NoError(t, dbConn.Create(&teamA).Error) + require.NoError(t, dbConn.Create(&teamB).Error) + + remoteUser := model.RemoteUser{ + ServiceID: fossa.ID, + RemoteUserID: 9001, + ServiceEmail: maintainer.Email, + RemoteRef: "alice-fossa", + } + require.NoError(t, dbConn.Create(&remoteUser).Error) + + link := model.RemoteTeamUser{ + ServiceID: fossa.ID, + TeamID: teamA.ID, + UserID: remoteUser.ID, + MaintainerID: &maintainer.ID, + } + require.NoError(t, dbConn.Create(&link).Error) + + invite := model.ServiceInvitation{ + ServiceID: fossa.ID, + RemoteTeamID: teamB.RemoteTeamID, + ProjectID: projectB.ID, + MaintainerID: &maintainer.ID, + ServiceEmail: maintainer.Email, + Status: "pending", + TeamAssignmentStatus: nil, + SentAt: &now, + LastCheckedAt: &now, + } + require.NoError(t, dbConn.Create(&invite).Error) + + s := &server{ + store: store, + sessions: newSessionStore(log.New(io.Discard, "", 0)), + cookieName: defaultSessionCookieName, + logger: log.New(io.Discard, "", 0), + } + staffSessionID := "staff-session" + s.sessions.Set(session{ + ID: staffSessionID, + Login: staff.GitHubAccount, + Role: roleStaff, + CreatedAt: now, + ExpiresAt: now.Add(time.Hour), + }) + + rec := performMaintainerGet(t, s, maintainer.ID, staffSessionID) + require.Equal(t, http.StatusOK, rec.Code) + + var response maintainerDetailResponse + require.NoError(t, json.NewDecoder(rec.Body).Decode(&response)) + require.Len(t, response.Services, 1) + + service := response.Services[0] + assert.Equal(t, "fossa", service.Kind) + assert.Equal(t, "CNCF FOSSA", service.Label) + assert.Equal(t, "registered", service.Account.State) + assert.Equal(t, "maintainer_email", service.Account.MatchedBy) + if assert.NotNil(t, service.Account.RemoteUserID) { + assert.Equal(t, uint(9001), *service.Account.RemoteUserID) + } + assert.Equal(t, "alice-fossa", service.Account.RemoteRef) + assert.Equal(t, maintainer.Email, service.Account.EmailUsed) + require.Len(t, service.Targets, 2) + + targetsByProject := map[uint]maintainerServiceTargetResponse{} + for _, target := range service.Targets { + targetsByProject[target.ProjectID] = target + } + + assert.Equal(t, "member", targetsByProject[projectA.ID].State) + assert.Equal(t, "pending", targetsByProject[projectB.ID].State) + assert.True(t, targetsByProject[projectB.ID].PendingInvite) +} + +func TestMaintainerFossaRefreshAction(t *testing.T) { + dbConn := setupPostgresTestDB(t) + store := db.NewSQLStore(dbConn) + now := time.Now() + + staff := model.StaffMember{ + Name: "Staff Tester", + GitHubAccount: "staff-tester", + Email: "staff@example.org", + } + require.NoError(t, dbConn.Create(&staff).Error) + + maintainer := model.Maintainer{ + Name: "Alice Example", + Email: "alice@example.org", + GitHubAccount: "alice-example", + GitHubEmail: "alice@github.example", + MaintainerStatus: model.ActiveMaintainer, + } + require.NoError(t, dbConn.Create(&maintainer).Error) + + project := model.Project{Name: "Project Refresh", Maturity: model.Sandbox} + require.NoError(t, dbConn.Create(&project).Error) + require.NoError(t, dbConn.Model(&project).Association("Maintainers").Append(&maintainer)) + + fossaService := model.Service{Name: "FOSSA", Description: "License scanning"} + require.NoError(t, dbConn.Create(&fossaService).Error) + require.NoError(t, dbConn.Model(&project).Association("Services").Append(&fossaService)) + + teamName := "Project Refresh Team" + team := model.RemoteTeam{ + ProjectID: project.ID, + ServiceID: fossaService.ID, + RemoteTeamID: 501, + RemoteTeamName: &teamName, + ProjectName: &project.Name, + } + require.NoError(t, dbConn.Create(&team).Error) + + invite := model.ServiceInvitation{ + ServiceID: fossaService.ID, + RemoteTeamID: team.RemoteTeamID, + ProjectID: project.ID, + MaintainerID: &maintainer.ID, + ServiceEmail: maintainer.Email, + Status: "pending", + LastCheckedAt: &now, + } + require.NoError(t, dbConn.Create(&invite).Error) + + fossaAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/users"): + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[{"id":9001,"username":"alice-fossa","email":"alice@example.org","github":{"name":"alice-example","email":"alice@github.example"},"bitbucketCloud":{"name":null,"email":null},"teamUsers":[{"roleId":3,"team":{"id":501,"name":"Project Refresh Team"}}]}]`)) + case r.Method == http.MethodGet && r.URL.Path == "/user-invitations": + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[{"email":"alice@example.org"}]`)) + default: + http.NotFound(w, r) + } + })) + defer fossaAPI.Close() + t.Setenv("FOSSA_API_BASE", fossaAPI.URL) + + s := &server{ + store: store, + sessions: newSessionStore(log.New(io.Discard, "", 0)), + cookieName: defaultSessionCookieName, + logger: log.New(io.Discard, "", 0), + fossaToken: "test-token", + } + staffSessionID := "staff-session" + s.sessions.Set(session{ + ID: staffSessionID, + Login: staff.GitHubAccount, + Role: roleStaff, + CreatedAt: now, + ExpiresAt: now.Add(time.Hour), + }) + + rec := performMaintainerAction(t, s, maintainer.ID, "refresh", staffSessionID) + require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) + + var response maintainerDetailResponse + require.NoError(t, json.NewDecoder(rec.Body).Decode(&response)) + require.Len(t, response.Services, 1) + assert.Equal(t, "registered", response.Services[0].Account.State) + assert.Equal(t, "member", response.Services[0].Targets[0].State) + + var remoteUser model.RemoteUser + require.NoError(t, dbConn.Where("service_id = ? AND remote_user_id = ?", fossaService.ID, 9001).First(&remoteUser).Error) + assert.Equal(t, "alice-fossa", remoteUser.RemoteRef) + + var link model.RemoteTeamUser + require.NoError(t, dbConn.Where("service_id = ? AND team_id = ? AND maintainer_id = ?", fossaService.ID, team.ID, maintainer.ID).First(&link).Error) + + var updatedInvite model.ServiceInvitation + require.NoError(t, dbConn.First(&updatedInvite, invite.ID).Error) + assert.Equal(t, "pending", updatedInvite.Status) +} + +func TestMaintainerFossaReconcileAction(t *testing.T) { + dbConn := setupPostgresTestDB(t) + store := db.NewSQLStore(dbConn) + now := time.Now() + + staff := model.StaffMember{ + Name: "Staff Tester", + GitHubAccount: "staff-tester", + Email: "staff@example.org", + } + require.NoError(t, dbConn.Create(&staff).Error) + + maintainer := model.Maintainer{ + Name: "Alice Example", + Email: "alice@example.org", + GitHubAccount: "alice-example", + GitHubEmail: "alice@github.example", + MaintainerStatus: model.ActiveMaintainer, + } + require.NoError(t, dbConn.Create(&maintainer).Error) + + projectA := model.Project{Name: "Project A", Maturity: model.Sandbox} + projectB := model.Project{Name: "Project B", Maturity: model.Graduated} + require.NoError(t, dbConn.Create(&projectA).Error) + require.NoError(t, dbConn.Create(&projectB).Error) + require.NoError(t, dbConn.Model(&projectA).Association("Maintainers").Append(&maintainer)) + require.NoError(t, dbConn.Model(&projectB).Association("Maintainers").Append(&maintainer)) + + fossaService := model.Service{Name: "FOSSA", Description: "License scanning"} + require.NoError(t, dbConn.Create(&fossaService).Error) + require.NoError(t, dbConn.Model(&projectA).Association("Services").Append(&fossaService)) + require.NoError(t, dbConn.Model(&projectB).Association("Services").Append(&fossaService)) + + teamAName := "Project A Team" + teamBName := "Project B Team" + teamA := model.RemoteTeam{ + ProjectID: projectA.ID, + ServiceID: fossaService.ID, + RemoteTeamID: 601, + RemoteTeamName: &teamAName, + ProjectName: &projectA.Name, + } + teamB := model.RemoteTeam{ + ProjectID: projectB.ID, + ServiceID: fossaService.ID, + RemoteTeamID: 602, + RemoteTeamName: &teamBName, + ProjectName: &projectB.Name, + } + require.NoError(t, dbConn.Create(&teamA).Error) + require.NoError(t, dbConn.Create(&teamB).Error) + + putBodies := make([]string, 0, 2) + fossaAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/users"): + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[{"id":9001,"username":"alice-fossa","email":"alice@example.org","github":{"name":"alice-example","email":"alice@github.example"},"bitbucketCloud":{"name":null,"email":null},"teamUsers":[]}]`)) + case r.Method == http.MethodGet && r.URL.Path == "/roles": + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[{"id":4,"scope":"team","name":"Team Admin"}]`)) + case r.Method == http.MethodPut && r.URL.Path == "/teams/601/users": + body, _ := io.ReadAll(r.Body) + putBodies = append(putBodies, string(body)) + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{}`)) + case r.Method == http.MethodPut && r.URL.Path == "/teams/602/users": + body, _ := io.ReadAll(r.Body) + putBodies = append(putBodies, string(body)) + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{}`)) + default: + http.NotFound(w, r) + } + })) + defer fossaAPI.Close() + t.Setenv("FOSSA_API_BASE", fossaAPI.URL) + + s := &server{ + store: store, + sessions: newSessionStore(log.New(io.Discard, "", 0)), + cookieName: defaultSessionCookieName, + logger: log.New(io.Discard, "", 0), + fossaToken: "test-token", + } + staffSessionID := "staff-session" + s.sessions.Set(session{ + ID: staffSessionID, + Login: staff.GitHubAccount, + Role: roleStaff, + CreatedAt: now, + ExpiresAt: now.Add(time.Hour), + }) + + rec := performMaintainerAction(t, s, maintainer.ID, "reconcile", staffSessionID) + require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) + + var response maintainerDetailResponse + require.NoError(t, json.NewDecoder(rec.Body).Decode(&response)) + require.Len(t, response.Services, 1) + for _, target := range response.Services[0].Targets { + assert.Equal(t, "member", target.State) + } + + require.Len(t, putBodies, 2) + assert.Contains(t, putBodies[0], `"userId":9001`) + assert.Contains(t, putBodies[0], `"roleId":4`) + assert.Contains(t, putBodies[1], `"userId":9001`) + assert.Contains(t, putBodies[1], `"roleId":4`) + + var links int64 + require.NoError(t, dbConn.Model(&model.RemoteTeamUser{}). + Where("service_id = ? AND maintainer_id = ?", fossaService.ID, maintainer.ID). + Count(&links).Error) + assert.Equal(t, int64(2), links) + + var invites []model.ServiceInvitation + require.NoError(t, dbConn.Where("service_id = ? AND maintainer_id = ?", fossaService.ID, maintainer.ID).Find(&invites).Error) + require.Len(t, invites, 2) + for _, invite := range invites { + assert.Equal(t, "accepted", invite.Status) + require.NotNil(t, invite.TeamAssignmentStatus) + assert.Equal(t, "done", *invite.TeamAssignmentStatus) + } +} + +func TestMaintainerFossaInviteAction(t *testing.T) { + dbConn := setupPostgresTestDB(t) + store := db.NewSQLStore(dbConn) + now := time.Now() + + staff := model.StaffMember{ + Name: "Staff Tester", + GitHubAccount: "staff-tester", + Email: "staff@example.org", + } + require.NoError(t, dbConn.Create(&staff).Error) + + maintainer := model.Maintainer{ + Name: "Alice Example", + Email: "alice@example.org", + GitHubAccount: "alice-example", + GitHubEmail: "alice@github.example", + MaintainerStatus: model.ActiveMaintainer, + } + require.NoError(t, dbConn.Create(&maintainer).Error) + + projectA := model.Project{Name: "Project A", Maturity: model.Sandbox} + projectB := model.Project{Name: "Project B", Maturity: model.Incubating} + require.NoError(t, dbConn.Create(&projectA).Error) + require.NoError(t, dbConn.Create(&projectB).Error) + require.NoError(t, dbConn.Model(&projectA).Association("Maintainers").Append(&maintainer)) + require.NoError(t, dbConn.Model(&projectB).Association("Maintainers").Append(&maintainer)) + + fossaService := model.Service{Name: "FOSSA", Description: "License scanning"} + require.NoError(t, dbConn.Create(&fossaService).Error) + require.NoError(t, dbConn.Model(&projectA).Association("Services").Append(&fossaService)) + require.NoError(t, dbConn.Model(&projectB).Association("Services").Append(&fossaService)) + + teamAName := "Project A Team" + teamBName := "Project B Team" + teamA := model.RemoteTeam{ + ProjectID: projectA.ID, + ServiceID: fossaService.ID, + RemoteTeamID: 701, + RemoteTeamName: &teamAName, + ProjectName: &projectA.Name, + } + teamB := model.RemoteTeam{ + ProjectID: projectB.ID, + ServiceID: fossaService.ID, + RemoteTeamID: 702, + RemoteTeamName: &teamBName, + ProjectName: &projectB.Name, + } + require.NoError(t, dbConn.Create(&teamA).Error) + require.NoError(t, dbConn.Create(&teamB).Error) + + fossaAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch { + case r.Method == http.MethodPost && r.URL.Path == "/organizations/162/invite": + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{}`)) + default: + http.NotFound(w, r) + } + })) + defer fossaAPI.Close() + t.Setenv("FOSSA_API_BASE", fossaAPI.URL) + + s := &server{ + store: store, + sessions: newSessionStore(log.New(io.Discard, "", 0)), + cookieName: defaultSessionCookieName, + logger: log.New(io.Discard, "", 0), + fossaToken: "test-token", + } + staffSessionID := "staff-session" + s.sessions.Set(session{ + ID: staffSessionID, + Login: staff.GitHubAccount, + Role: roleStaff, + CreatedAt: now, + ExpiresAt: now.Add(time.Hour), + }) + + rec := performMaintainerAction(t, s, maintainer.ID, "invite", staffSessionID) + require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) + + var response maintainerDetailResponse + require.NoError(t, json.NewDecoder(rec.Body).Decode(&response)) + require.Len(t, response.Services, 1) + assert.Equal(t, "invited", response.Services[0].Account.State) + + var invites []model.ServiceInvitation + require.NoError(t, dbConn.Where("service_id = ? AND maintainer_id = ?", fossaService.ID, maintainer.ID).Order("project_id asc").Find(&invites).Error) + require.Len(t, invites, 2) + assert.Equal(t, projectA.ID, invites[0].ProjectID) + assert.Equal(t, projectB.ID, invites[1].ProjectID) + for _, invite := range invites { + assert.Equal(t, "pending", invite.Status) + assert.Equal(t, maintainer.Email, invite.ServiceEmail) + } +} + func TestParseGitHubIssueURL(t *testing.T) { t.Run("parses github issue url", func(t *testing.T) { owner, repo, number, err := parseGitHubIssueURL("https://github.com/cncf/sandbox/issues/1234") diff --git a/db/store_impl_test.go b/db/store_impl_test.go index cd20d64..27f32b6 100644 --- a/db/store_impl_test.go +++ b/db/store_impl_test.go @@ -164,13 +164,13 @@ func TestUpsertMaintainer_FillsMissingFields(t *testing.T) { // Existing maintainer with missing name and GitHub account. existing := model.Maintainer{ Name: "", - Email: "accorell@amazon.com", + Email: "adrian@example.com", GitHubAccount: "GITHUB_MISSING", MaintainerStatus: model.ActiveMaintainer, } require.NoError(t, db.Create(&existing).Error) - maintainer, err := store.UpsertMaintainer(project.ID, "Adrian Palacios", "accorell@amazon.com", "adpaco-aws", "Amazon") + maintainer, err := store.UpsertMaintainer(project.ID, "Adrian Palacios", "adrian@example.com", "adpaco-aws", "Amazon") require.NoError(t, err) require.NotNil(t, maintainer) assert.Equal(t, existing.ID, maintainer.ID) @@ -179,7 +179,7 @@ func TestUpsertMaintainer_FillsMissingFields(t *testing.T) { require.NoError(t, db.First(&refreshed, existing.ID).Error) assert.Equal(t, "Adrian Palacios", refreshed.Name) assert.Equal(t, "adpaco-aws", refreshed.GitHubAccount) - assert.Equal(t, "accorell@amazon.com", refreshed.Email) + assert.Equal(t, "adrian@example.com", refreshed.Email) assert.NotNil(t, refreshed.CompanyID) assert.NotEqual(t, uint(0), *refreshed.CompanyID) diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..f8304e7 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,25 @@ +# Development + +## Git hooks + +This repo uses a local git hooks directory to prevent committing unencrypted secrets +and likely PII in staged files. + +Install hooks for this repo: + +```bash +make githooks-install +``` + +The pre-commit hook currently runs two checks: + +- `scripts/check-sops-secrets.sh --staged` + - blocks commits if any `deploy/secrets/*.yaml` files are missing SOPS metadata + or contain plaintext values for secret-like keys +- `scripts/check-pii.sh --staged` + - scans staged text files for likely personal email addresses and obvious tokens + - permits approved fixture/example values via + [`scripts/pii-allowlist.regex`](/home/rk/cncf/gh/maintainer-d/scripts/pii-allowlist.regex) + +If the PII check flags a legitimate fixture, either sanitize it further or add a +targeted allowlist pattern rather than disabling the hook. diff --git a/features/web/maintainer_profile.feature b/features/web/maintainer_profile.feature index b61c705..6b8f8d6 100644 --- a/features/web/maintainer_profile.feature +++ b/features/web/maintainer_profile.feature @@ -8,3 +8,77 @@ Feature: Maintainer profile page When I search for "Antonio" And I click on maintainer "Antonio Example" Then I see the maintainer card for "Antonio Example" + + Rule: Staff can inspect and repair maintainer service associations + - The maintainer page shows what maintainer-d knows about a maintainer's association with remote services + - The maintainer page shows which project service assignments imply that the maintainer should have remote service access + - Remote service checks use the maintainer email address and may also use the maintainer GitHub email address + - From the maintainer page staff can reconcile missing remote service access + - If a maintainer is not registered with CNCF FOSSA, staff can send a CNCF FOSSA invite from the maintainer page + + Scenario: Staff can view service associations on a maintainer page + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer belongs to one or more projects + When I open the maintainer page + Then I see a service associations section + And I see which remote services the maintainer is associated with + And I see which project service assignments imply that the maintainer should be associated with those services + + Scenario: Staff can recheck remote service associations after updating a maintainer email + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer is associated with a project that uses FOSSA + When I update the maintainer email address + And I save the maintainer record + And I refresh the maintainer's remote service associations + Then maintainer-d checks whether the maintainer exists on the remote service using the updated maintainer email address + And maintainer-d may also check using the maintainer GitHub email address + And the maintainer page shows the updated remote service association status + + Scenario: Staff can see when a maintainer is known to FOSSA but missing from a required project team + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer belongs to a project that uses FOSSA + And the maintainer exists in CNCF FOSSA + And the maintainer is not a member of that project's FOSSA team + When I open the maintainer page + Then I see that the maintainer is associated with CNCF FOSSA + And I see that the maintainer is missing from the FOSSA team required by the project + + Scenario: Staff can reconcile a known FOSSA user to all missing required project teams + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer belongs to multiple active projects that use FOSSA + And the maintainer exists in CNCF FOSSA + And the maintainer is missing from one or more required FOSSA teams + When I reconcile the maintainer's FOSSA access from the maintainer page + Then maintainer-d adds the maintainer to every missing required FOSSA team using the FOSSA REST API + And the maintainer page shows the full set of required FOSSA teams for the maintainer + And the maintainer page shows that the maintainer is now associated with those FOSSA teams + + Scenario: Staff can invite a maintainer to CNCF FOSSA from the maintainer page + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer belongs to a project that uses FOSSA + And the maintainer does not exist in CNCF FOSSA + When I send a CNCF FOSSA invite from the maintainer page + Then maintainer-d sends a CNCF FOSSA invitation to the maintainer + And the maintainer page shows that FOSSA onboarding is pending + + Scenario: Staff can reconcile FOSSA access after a maintainer accepts an invitation + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer belongs to one or more projects that use FOSSA + And a CNCF FOSSA invitation is pending for the maintainer + When the FOSSA invitation is accepted + And I refresh the maintainer's remote service associations + Then maintainer-d reconciles the maintainer to each required FOSSA team + And the maintainer page shows that the maintainer is associated with those FOSSA teams + + Scenario: Staff can see which identifier matched a remote account + Given I am signed in as a staff member + And a maintainer exists in maintainer-d + And the maintainer exists in CNCF FOSSA + When I open the maintainer page + Then I see whether the maintainer was matched by maintainer email address or GitHub email address diff --git a/microcks/fossa-api-mock.yaml b/microcks/fossa-api-mock.yaml new file mode 100644 index 0000000..9597785 --- /dev/null +++ b/microcks/fossa-api-mock.yaml @@ -0,0 +1,429 @@ +openapi: 3.1.0 +info: + title: FOSSA API + version: 4.32.3 +servers: + - url: https://app.fossa.com/api +paths: + /teams: + get: + operationId: listTeams + responses: + "200": + description: Teams list + content: + application/json: + examples: + default_teams: + value: + - id: 101 + organizationId: 162 + name: Project Fossa Full + defaultRoleId: 4 + autoAddUsers: false + uniqueIdentifier: project-fossa-full + - id: 102 + organizationId: 162 + name: Project Fossa Partial + defaultRoleId: 4 + autoAddUsers: false + uniqueIdentifier: project-fossa-partial + - id: 103 + organizationId: 162 + name: Project Fossa Invites + defaultRoleId: 4 + autoAddUsers: false + uniqueIdentifier: project-fossa-invites + - id: 104 + organizationId: 162 + name: Project Fossa Missing Email + defaultRoleId: 4 + autoAddUsers: false + uniqueIdentifier: project-fossa-missing-email + post: + operationId: createTeam + requestBody: + required: true + content: + application/json: + examples: + create_no_license: + value: + name: Project No License + responses: + "200": + description: Team created + content: + application/json: + examples: + create_no_license: + value: + id: 105 + organizationId: 162 + name: Project No License + defaultRoleId: 4 + autoAddUsers: false + uniqueIdentifier: project-no-license + /teams/{id}/members: + get: + operationId: listTeamMembers + parameters: + - name: id + in: path + required: true + schema: + type: integer + examples: + fossa_full: + value: 101 + fossa_partial: + value: 102 + fossa_invites: + value: 103 + fossa_missing: + value: 104 + no_license: + value: 105 + responses: + "200": + description: Team members list + content: + application/json: + examples: + fossa_full: + value: + results: + - userId: 1 + roleId: 4 + username: antonio-example + email: antonio.example@test.dev + - userId: 2 + roleId: 4 + username: renee-sample + email: renee.sample@example.dev + pageSize: 2 + page: 0 + totalCount: 2 + fossa_partial: + value: + results: + - userId: 3 + roleId: 4 + username: alex-example + email: alex@example.dev + pageSize: 1 + page: 0 + totalCount: 1 + fossa_invites: + value: + results: + - userId: 4 + roleId: 4 + username: priya-demo + email: priya.demo@test.dev + pageSize: 1 + page: 0 + totalCount: 1 + fossa_missing: + value: + results: [] + pageSize: 0 + page: 0 + totalCount: 0 + no_license: + value: + results: [] + pageSize: 0 + page: 0 + totalCount: 0 + /users: + get: + operationId: listUsers + parameters: + - name: count + in: query + required: false + schema: + type: integer + examples: + default_users: + value: 100 + - name: page + in: query + required: false + schema: + type: integer + examples: + default_users: + value: 0 + responses: + "200": + description: Users list + content: + application/json: + examples: + default_users: + value: + - id: 1 + username: antonio.example@test.dev + email: antonio.example@test.dev + github: + name: antonio-example + email: antonio@example.dev + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 101 + name: Project Fossa Full + - id: 2 + username: renee-sample + email: renee@example.dev + github: + name: renee-sample + email: renee@example.dev + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 101 + name: Project Fossa Full + - id: 3 + username: alex@example.dev + email: alex@example.dev + github: + name: alex-example + email: alex@example.dev + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 999 + name: Another Team + - id: 4 + username: priya.demo@test.dev + email: priya.demo@test.dev + github: + name: priya-demo + email: priya@example.dev + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 103 + name: Project Fossa Invites + - id: 5 + username: jun.example@test.dev + email: jun.example@test.dev + github: + name: jun-example + email: jun@example.dev + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 103 + name: Project Fossa Invites + - id: 94780 + username: bob@affiliated-company.tld + email: bob@affiliated-company.tld + github: + name: bob + email: bob@users.noreply.github.com + bitbucketCloud: + name: null + email: null + teamUsers: + - roleId: 4 + team: + id: 999 + name: Another Team + /roles: + get: + operationId: listRoles + responses: + "200": + description: Roles list + content: + application/json: + examples: + default_roles: + value: + - id: 1 + scope: organization + name: Admin + - id: 2 + scope: organization + name: Editor + - id: 3 + scope: organization + name: Viewer + - id: 4 + scope: team + name: Team Admin + - id: 5 + scope: team + name: Team Editor + - id: 6 + scope: team + name: Team Viewer + /user-invitations: + get: + operationId: listUserInvitations + responses: + "200": + description: Pending invitations + content: + application/json: + examples: + no_pending_invites: + value: [] + /organizations/{organizationId}/invite: + post: + operationId: inviteUserToOrganization + parameters: + - name: organizationId + in: path + required: true + schema: + type: string + examples: + send_invite: + value: "162" + requestBody: + required: true + content: + application/json: + examples: + send_invite: + value: + email: invitee@example.test + responses: + "200": + description: Invitation created + content: + application/json: + examples: + send_invite: + value: {} + /teams/{id}/users: + put: + operationId: updateTeamUsers + parameters: + - name: id + in: path + required: true + schema: + type: integer + examples: + add_team_admin_full: + value: 101 + add_team_admin_partial: + value: 102 + add_team_admin_invites: + value: 103 + add_team_admin_missing: + value: 104 + add_team_admin_no_license: + value: 105 + add_team_admin_legacy: + value: 102209 + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - action + properties: + action: + type: string + enum: + - add + - remove + - replace + users: + type: array + items: + type: object + required: + - id + properties: + id: + type: integer + roleId: + type: integer + examples: + add_team_admin_partial: + value: + action: add + users: + - id: 94780 + roleId: 4 + add_team_admin_no_license: + value: + action: add + users: + - id: 2 + roleId: 4 + responses: + "200": + description: Team users updated + content: + application/json: + examples: + add_team_admin_partial: + value: + id: 102 + users: + - userId: 1 + roleId: 4 + add_team_admin_full: + value: + id: 101 + users: + - userId: 1 + roleId: 4 + - userId: 2 + roleId: 4 + add_team_admin_invites: + value: + id: 103 + users: + - userId: 4 + roleId: 4 + - userId: 5 + roleId: 4 + add_team_admin_missing: + value: + id: 104 + users: + - userId: 94780 + roleId: 4 + add_team_admin_no_license: + value: + id: 105 + users: + - userId: 2 + roleId: 4 + add_team_admin_legacy: + value: + id: 102209 + users: + - userId: 92921 + roleId: 4 + - userId: 92922 + roleId: 4 + - userId: 94780 + roleId: 4 diff --git a/model/main.go b/model/main.go index 0b7c185..c142e96 100644 --- a/model/main.go +++ b/model/main.go @@ -87,9 +87,9 @@ func (m Maturity) IsValid() bool { type Maintainer struct { gorm.Model Name string - Email string `gorm:"size:254;default:EMAIL_MISSING"` + Email string `gorm:"size:254;default:EMAIL_MISSING"` // Primary/Work Email GitHubAccount string `gorm:"size:100;default:GITHUB_MISSING"` - GitHubEmail string `gorm:"size:100;default:GITHUB_MISSING"` + GitHubEmail string `gorm:"size:100;default:GITHUB_MISSING"` // Email used for Git Commits on GitHub MaintainerStatus MaintainerStatus `gorm:"type:text"` ImportWarnings string Projects []Project `gorm:"many2many:maintainer_projects;joinForeignKey:MaintainerID;joinReferences:ProjectID"` @@ -201,6 +201,7 @@ type RemoteUser struct { ServiceGitHubName *string } +// Orchestrates Inviations maintainer-d sends to Maintaienrs to join services type ServiceInvitation struct { gorm.Model ServiceID uint `gorm:"index;uniqueIndex:idx_service_invite_project_email"` // FK to Service diff --git a/plugins/fossa/client.go b/plugins/fossa/client.go index 03bb771..856ec39 100644 --- a/plugins/fossa/client.go +++ b/plugins/fossa/client.go @@ -119,6 +119,55 @@ func (c *Client) FetchUsers() ([]User, error) { return allUsers, nil } +type Role struct { + ID int `json:"id"` + Scope string `json:"scope"` + Name string `json:"name"` +} + +func (c *Client) FetchRoles() ([]Role, error) { + req, err := http.NewRequest("GET", c.APIBase+"/roles", nil) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Authorization", "Bearer "+c.APIKey) + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("request failed: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %w", err) + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("FetchRoles failed: %s – %s", resp.Status, string(body)) + } + + var roles []Role + if err := json.Unmarshal(body, &roles); err != nil { + return nil, fmt.Errorf("failed to decode response: %w", err) + } + return roles, nil +} + +func (c *Client) ResolveTeamAdminRoleID() (int, error) { + roles, err := c.FetchRoles() + if err != nil { + return 0, err + } + for _, role := range roles { + if strings.EqualFold(strings.TrimSpace(role.Scope), "team") && + strings.EqualFold(strings.TrimSpace(role.Name), "Team Admin") { + return role.ID, nil + } + } + return 0, fmt.Errorf("ResolveTeamAdminRoleID: Team Admin role not found") +} + // FetchUserInvitations GETs /api/user-invitations - Retrieves all active (non-expired) user invitations for an // organization func (c *Client) FetchUserInvitations() (string, error) { @@ -448,7 +497,8 @@ func (c *Client) AddUserToTeamByEmailWithResponse(teamID uint, email string, rol bodyPayload := map[string]interface{}{ "users": []map[string]interface{}{ { - "id": uid, + "id": uid, + "userId": uid, }, }, "action": "add", diff --git a/plugins/fossa/swagger.json b/plugins/fossa/swagger.json new file mode 100644 index 0000000..7a13025 --- /dev/null +++ b/plugins/fossa/swagger.json @@ -0,0 +1,73126 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "FOSSA API", + "description": "OpenAPI Specification for public FOSSA APIs", + "contact": { + "name": "FOSSA", + "url": "fossa.com", + "email": "support@fossa.com" + }, + "version": "4.32.3" + }, + "servers": [ + { + "url": "https://app.fossa.com/api", + "description": "FOSSA's production api server (for cloud only)" + } + ], + "x-readme": { + "samples-languages": [ + "curl", + "powershell", + "python" + ] + }, + "externalDocs": { + "url": "https://docs.fossa.com", + "description": "product documentation and product guides" + }, + "tags": [ + { + "name": "Issues", + "description": "Issues with a given project or package" + }, + { + "name": "Issue Filters", + "description": "Saved issue filters, including sort and group options" + }, + { + "name": "Issue Overview", + "description": "APIs supporting the Issue Overview dashboard" + }, + { + "name": "Projects", + "description": "Projects within your organization" + }, + { + "name": "Revisions", + "description": "Revisions in a project" + }, + { + "name": "Dependencies", + "description": "Dependencies of a given project or release group" + }, + { + "name": "CLI", + "description": "Related to the FOSSA CLI tool" + }, + { + "name": "Organization Labels", + "description": "Related to labels for your organization's projects" + }, + { + "name": "Project Labels", + "description": "Related to project-level labels" + }, + { + "name": "Package Labels", + "description": "Related to package-level labels" + }, + { + "name": "Package Observability", + "description": "APIs for viewing details about the packages used across your organization" + }, + { + "name": "Release Groups", + "description": "Release groups within your organization" + }, + { + "name": "SBOM", + "description": "APIs related to Software Bill of Materials (SBOM) functionality" + }, + { + "name": "Vulnerabilities", + "description": "APIs supporting vulnerabilities" + }, + { + "name": "Organization Settings", + "description": "APIs supporting organization settings" + }, + { + "name": "Jira Integration Settings", + "description": "APIs supporting Jira integration configuration" + }, + { + "name": "Builds", + "description": "APIs supporting builds for a given project or revision" + }, + { + "name": "Portal", + "description": "APIs to manage your organization's Portal" + }, + { + "name": "Audit Logs", + "description": "APIs to manage audit logs" + }, + { + "name": "Organization Limits", + "description": "APIs for managing your organization" + }, + { + "name": "Components", + "description": "APIs to upload components" + }, + { + "name": "Custom Risk Scores", + "description": "APIs for managing custom risk scores on issues" + }, + { + "name": "Users", + "description": "APIs to manage Users" + }, + { + "name": "Teams", + "description": "APIs to manage Teams" + }, + { + "name": "Team Groups", + "description": "APIs to manage Team Groups" + }, + { + "name": "Roles", + "description": "APIs to manage Roles" + }, + { + "name": "GitHub App", + "description": "Manage GitHub App integration" + }, + { + "name": "Binary", + "description": "APIs related to Binary Decomposition functionality" + }, + { + "name": "OIDC", + "description": "APIs for managing OIDC authentication providers and trust relationships" + }, + { + "name": "Snippets", + "description": "APIs related to the Snippet Detection feature" + }, + { + "name": "License Conclusions", + "description": "APIs for managing license conclusions on dependencies" + }, + { + "name": "Policies", + "description": "APIs for managing policies" + }, + { + "name": "Report Options", + "description": "APIs for managing saved report options" + } + ], + "paths": { + "/license-conclusions/conclude": { + "put": { + "operationId": "addLicenseConclusion", + "description": "Add a license to the license conclusions for a dependency revision. Requires Edit permission on the dependency revision.", + "tags": [ + "License Conclusions" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencyRevisionLocator": { + "type": "string", + "description": "The locator of the dependency revision" + }, + "scope": { + "oneOf": [ + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "PROJECT" + ], + "description": "Project-scoped conclusion" + }, + "projectLocator": { + "type": "string", + "description": "The locator of the project" + } + }, + "required": [ + "scope", + "projectLocator" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "REVISION" + ], + "description": "Revision-scoped conclusion" + }, + "projectLocator": { + "type": "string", + "description": "The locator of the project" + }, + "revisionLocator": { + "type": "string", + "description": "The locator of the revision" + } + }, + "required": [ + "scope", + "projectLocator", + "revisionLocator" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "RELEASE_GROUP" + ], + "description": "Release group-scoped conclusion" + }, + "releaseGroupId": { + "type": "integer", + "description": "The ID of the release group" + } + }, + "required": [ + "scope", + "releaseGroupId" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "RELEASE" + ], + "description": "Release-scoped conclusion" + }, + "releaseGroupId": { + "type": "integer", + "description": "The ID of the release group" + }, + "releaseId": { + "type": "integer", + "description": "The ID of the release" + } + }, + "required": [ + "scope", + "releaseGroupId", + "releaseId" + ] + } + ] + }, + "licenseId": { + "type": "string", + "description": "The license ID to add or remove" + }, + "originId": { + "type": "string", + "description": "Optional origin revision or release ID to trigger an issue scan" + } + }, + "required": [ + "dependencyRevisionLocator", + "scope", + "licenseId" + ] + }, + "examples": { + "projectScope": { + "summary": "Project-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "PROJECT", + "projectLocator": "git+github.com/fossas/fossa-cli$main" + }, + "licenseId": "MIT", + "originId": "git+github.com/fossas/fossa-cli$main" + } + }, + "revisionScope": { + "summary": "Revision-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "REVISION", + "projectLocator": "git+github.com/fossas/fossa-cli$main", + "revisionLocator": "git+github.com/fossas/fossa-cli$abc123" + }, + "licenseId": "MIT" + } + }, + "releaseGroupScope": { + "summary": "Release group-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "RELEASE_GROUP", + "releaseGroupId": 123 + }, + "licenseId": "MIT", + "originId": "456" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "License conclusion added successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencyRevisionLocator": { + "type": "string", + "description": "The locator of the dependency revision" + }, + "scope": { + "type": "string", + "enum": [ + "PROJECT", + "REVISION", + "RELEASE_GROUP", + "RELEASE" + ], + "nullable": false, + "description": "The scope of the license conclusion" + }, + "scopeId": { + "type": "string", + "nullable": false, + "description": "The ID of the scope (project locator, revision locator, release group ID, etc.)" + }, + "concludedLicenses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The list of concluded licenses for this dependency" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the conclusion was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the conclusion was last updated" + } + }, + "required": [ + "dependencyRevisionLocator", + "scope", + "scopeId", + "concludedLicenses", + "createdAt", + "updatedAt" + ] + }, + "examples": { + "licenseConclusionResponse": { + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": "PROJECT", + "scopeId": "git+github.com/fossas/fossa-cli$main", + "concludedLicenses": [ + "MIT", + "Apache-2.0" + ], + "createdAt": "2024-01-15T10:30:00Z", + "updatedAt": "2024-01-15T10:30:00Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "invalidRequest": { + "summary": "Invalid request body", + "value": { + "error": "Invalid request body: missing required field" + } + }, + "missingScopeId": { + "summary": "Missing scopeId for scoped conclusion", + "value": { + "error": "scopeId is required for project/revision scopes" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "forbidden": { + "summary": "Insufficient permissions", + "value": { + "error": "You do not have permission to edit license conclusions for this scope" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "revisionNotFound": { + "summary": "Origin revision not found", + "value": { + "error": "Origin revision with locator git+github.com/fossas/fossa-cli$abc123 not found or you don't have access" + } + }, + "releaseNotFound": { + "summary": "Origin release not found", + "value": { + "error": "Origin release with locator 123 not found or you don't have access" + } + } + } + } + } + } + } + } + }, + "/license-conclusions/unconclude": { + "put": { + "operationId": "removeLicenseConclusion", + "description": "Remove a license from the license conclusions for a dependency revision. Requires Edit permission for the dependency revision.", + "tags": [ + "License Conclusions" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencyRevisionLocator": { + "type": "string", + "description": "The locator of the dependency revision" + }, + "scope": { + "oneOf": [ + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "PROJECT" + ], + "description": "Project-scoped conclusion" + }, + "projectLocator": { + "type": "string", + "description": "The locator of the project" + } + }, + "required": [ + "scope", + "projectLocator" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "REVISION" + ], + "description": "Revision-scoped conclusion" + }, + "projectLocator": { + "type": "string", + "description": "The locator of the project" + }, + "revisionLocator": { + "type": "string", + "description": "The locator of the revision" + } + }, + "required": [ + "scope", + "projectLocator", + "revisionLocator" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "RELEASE_GROUP" + ], + "description": "Release group-scoped conclusion" + }, + "releaseGroupId": { + "type": "integer", + "description": "The ID of the release group" + } + }, + "required": [ + "scope", + "releaseGroupId" + ] + }, + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": [ + "RELEASE" + ], + "description": "Release-scoped conclusion" + }, + "releaseGroupId": { + "type": "integer", + "description": "The ID of the release group" + }, + "releaseId": { + "type": "integer", + "description": "The ID of the release" + } + }, + "required": [ + "scope", + "releaseGroupId", + "releaseId" + ] + } + ] + }, + "licenseId": { + "type": "string", + "description": "The license ID to add or remove" + }, + "originId": { + "type": "string", + "description": "Optional origin revision or release ID to trigger an issue scan" + } + }, + "required": [ + "dependencyRevisionLocator", + "scope", + "licenseId" + ] + }, + "examples": { + "projectScope": { + "summary": "Project-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "PROJECT", + "projectLocator": "git+github.com/fossas/fossa-cli$main" + }, + "licenseId": "MIT", + "originId": "git+github.com/fossas/fossa-cli$main" + } + }, + "revisionScope": { + "summary": "Revision-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "REVISION", + "projectLocator": "git+github.com/fossas/fossa-cli$main", + "revisionLocator": "git+github.com/fossas/fossa-cli$abc123" + }, + "licenseId": "MIT" + } + }, + "releaseGroupScope": { + "summary": "Release group-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "RELEASE_GROUP", + "releaseGroupId": 123 + }, + "licenseId": "MIT", + "originId": "456" + } + }, + "globalScope": { + "summary": "Global-scoped conclusion", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": { + "scope": "GLOBAL" + }, + "licenseId": "MIT" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "License conclusion removed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencyRevisionLocator": { + "type": "string", + "description": "The locator of the dependency revision" + }, + "scope": { + "type": "string", + "enum": [ + "PROJECT", + "REVISION", + "RELEASE_GROUP", + "RELEASE" + ], + "nullable": false, + "description": "The scope of the license conclusion" + }, + "scopeId": { + "type": "string", + "nullable": false, + "description": "The ID of the scope (project locator, revision locator, release group ID, etc.)" + }, + "concludedLicenses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The list of concluded licenses for this dependency" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the conclusion was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the conclusion was last updated" + } + }, + "required": [ + "dependencyRevisionLocator", + "scope", + "scopeId", + "concludedLicenses", + "createdAt", + "updatedAt" + ] + }, + "examples": { + "licenseConclusionResponse": { + "summary": "License removed from conclusions", + "value": { + "dependencyRevisionLocator": "npm+lodash$4.17.21", + "scope": "PROJECT", + "scopeId": "git+github.com/fossas/fossa-cli$main", + "concludedLicenses": [ + "Apache-2.0" + ], + "createdAt": "2024-01-15T10:30:00Z", + "updatedAt": "2024-01-15T11:00:00Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "invalidRequest": { + "summary": "Invalid request body", + "value": { + "error": "Invalid request body: missing required field" + } + }, + "missingScopeId": { + "summary": "Missing scopeId for scoped conclusion", + "value": { + "error": "scopeId is required for project/revision scopes" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "forbidden": { + "summary": "Insufficient permissions", + "value": { + "error": "You do not have permission to edit license conclusions for this scope" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "revisionNotFound": { + "summary": "Origin revision not found", + "value": { + "error": "Origin revision with locator git+github.com/fossas/fossa-cli$abc123 not found or you don't have access" + } + }, + "releaseNotFound": { + "summary": "Origin release not found", + "value": { + "error": "Origin release with locator 123 not found or you don't have access" + } + } + } + } + } + } + } + } + }, + "/services/github-app/installation-url": { + "get": { + "operationId": "getGitHubAppInstallationUrl", + "x-internal": true, + "description": "Redirects to the GitHub App installation page.", + "tags": [ + "GitHub App" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "302": { + "description": "Redirects to the GitHub App installation page." + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/categories": { + "get": { + "operationId": "getIssuesByCategory", + "description": "Get the number of active issues by category", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Number of active issues for each issue category", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "licensing": { + "type": "integer" + }, + "quality": { + "type": "integer" + }, + "vulnerability": { + "type": "integer" + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "licensing": { + "type": "integer" + }, + "quality": { + "type": "integer" + }, + "vulnerability": { + "type": "integer" + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "licensing": 0, + "quality": 0, + "vulnerability": 0 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/types": { + "get": { + "operationId": "getIssuesByType", + "description": "Get the number of active issues by type", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Number of active issues for each issue type", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "policy_conflict": { + "type": "integer" + }, + "policy_flag": { + "type": "integer" + }, + "unlicensed_dependency": { + "type": "integer" + }, + "outdated_dependency": { + "type": "integer" + }, + "vulnerability": { + "type": "integer" + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "policy_conflict": { + "type": "integer" + }, + "policy_flag": { + "type": "integer" + }, + "unlicensed_dependency": { + "type": "integer" + }, + "outdated_dependency": { + "type": "integer" + }, + "vulnerability": { + "type": "integer" + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "policy_conflict": 0, + "policy_flag": 0, + "unlicensed_dependency": 0, + "outdated_dependency": 0, + "vulnerability": 0 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/statuses": { + "get": { + "operationId": "getIssueStatuses", + "description": "Get a count of issues by status, matching the provided filters", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "ids[]", + "description": "Filter by specific issue IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + { + "name": "filter[revisionIds][]", + "description": "Filter by specific revision IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[search]", + "description": "Filter by package name or CVE (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filter[depths][]", + "description": "Filter by issue depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "deep" + ] + } + } + }, + { + "name": "filter[ticketed][]", + "description": "Filter by ticketed status. Only available to premium users.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + } + } + }, + { + "name": "filter[containerLayers][]", + "description": "Filter by container layer", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + } + }, + { + "name": "filter[type][]", + "description": "Filter by licensing issue type (when category is \"licensing\") or quality issue type (when category is \"quality\")\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency" + ] + } + } + ] + } + }, + { + "name": "filter[packageManagers][]", + "description": "Filter by specific package managers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[projectLabels][]", + "description": "Filter by specific project labels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[identification][]", + "description": "Filter by license identification (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + } + } + }, + { + "name": "filter[severity][]", + "description": "Filter by vuln severity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "filter[foundAfter]", + "description": "Include only issues found on after a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[hasFix][]", + "description": "Filter by vuln fixability (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "filter[upgradeDistance][]", + "description": "Filter by vuln upgrade distance (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + } + } + }, + { + "name": "filter[exploitMaturity][]", + "description": "Filter by vuln exploit maturity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + } + } + }, + { + "name": "filter[ignoreReason][]", + "description": "Filter by vuln ignore reason (when category is \"vulnerability\") This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + } + } + }, + { + "name": "filter[licenses][]", + "description": "Filter by issues affected by a set of license ID's (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[issueSource][]", + "description": "Filter by issue source. Use 'dependency' and 'snippet' to filter by whether the issue comes from a dependency or a code snippet. When the vendored dependency detection feature is enabled, use 'managed-dependency' and 'vendored-dependency' to filter dependency issues by whether the dependency is managed or vendored.\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "dependency", + "snippet" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed-dependency", + "vendored-dependency", + "snippet" + ] + } + } + ] + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Number of matching issues and revisions", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "issues": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "revisions": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "issues": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "revisions": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "issues": { + "active": 0, + "ignored": 0 + }, + "revision": { + "active": 0, + "ignored": 0 + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/compare/summaries": { + "get": { + "operationId": "getIssueDiffComparisonSummaries", + "description": "Retrieve the counts for the different change statuses when in Issue Comparison mode. Supports both Project (revision comparison) and Release Group (release comparison) scopes.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][release]", + "description": "The release ID to compare issues with. Only available for Release Group Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "ids[]", + "description": "Filter by specific issue IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + { + "name": "filter[revisionIds][]", + "description": "Filter by specific revision IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[search]", + "description": "Filter by package name or CVE (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filter[depths][]", + "description": "Filter by issue depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "deep" + ] + } + } + }, + { + "name": "filter[ticketed][]", + "description": "Filter by ticketed status. Only available to premium users.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + } + } + }, + { + "name": "filter[containerLayers][]", + "description": "Filter by container layer", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + } + }, + { + "name": "filter[type][]", + "description": "Filter by licensing issue type (when category is \"licensing\") or quality issue type (when category is \"quality\")\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency" + ] + } + } + ] + } + }, + { + "name": "filter[packageManagers][]", + "description": "Filter by specific package managers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[cwes][]", + "description": "Filter by specific CWE identifiers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[projectLabels][]", + "description": "Filter by specific project labels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[identification][]", + "description": "Filter by license identification (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + } + } + }, + { + "name": "filter[severity][]", + "description": "Filter by vuln severity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "filter[foundAfter]", + "description": "Include only issues found on after a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[hasFix][]", + "description": "Filter by vuln fixability (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "filter[upgradeDistance][]", + "description": "Filter by vuln upgrade distance (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + } + } + }, + { + "name": "filter[exploitMaturity][]", + "description": "Filter by vuln exploit maturity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + } + } + }, + { + "name": "filter[ignoreReason][]", + "description": "Filter by vuln ignore reason (when category is \"vulnerability\") This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + } + } + }, + { + "name": "filter[epss]", + "description": "Filter by epss 'score' or 'percentile'. All fields are required. Only available to premium users.", + "in": "query", + "style": "deepObject", + "explode": true, + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "score", + "percentile" + ] + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + } + }, + "examples": { + "filterByScore": { + "value": { + "type": "score", + "min": 0.01, + "max": 0.25 + }, + "summary": "Filter to issues with a score between 0.1 and 0.25 (inclusive)" + }, + "filterByPercentile": { + "value": { + "type": "percentile", + "min": 0.85, + "max": 1 + }, + "summary": "Filter to issues above the 85th percentile (inclusive)" + } + } + }, + { + "name": "filter[confidence][]", + "description": "Filter issues by their binary dependency confidence level(s)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "High", + "Medium", + "Low", + "Unknown" + ] + } + } + }, + { + "name": "filter[issueSource][]", + "description": "Filter by issue source. Use 'dependency' and 'snippet' to filter by whether the issue comes from a dependency or a code snippet. When the vendored dependency detection feature is enabled, use 'managed-dependency' and 'vendored-dependency' to filter dependency issues by whether the dependency is managed or vendored.\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "dependency", + "snippet" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed-dependency", + "vendored-dependency", + "snippet" + ] + } + } + ] + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Vulnerability, licensing, or quality issues response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "issues": { + "type": "object", + "properties": { + "new": { + "type": "integer" + }, + "remediated": { + "type": "integer" + }, + "unchanged": { + "type": "integer" + } + } + }, + "revisions": { + "type": "object", + "properties": { + "new": { + "type": "integer" + }, + "remediated": { + "type": "integer" + }, + "unchanged": { + "type": "integer" + } + } + } + } + }, + "examples": { + "summaries": { + "value": { + "issues": { + "new": 10, + "remediated": 5, + "unchanged": 3 + }, + "revisions": { + "new": 10, + "remediated": 5, + "unchanged": 3 + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "406": { + "description": "Not Acceptable", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Accept": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2015, + "message": "Invalid accept:", + "name": "NotAcceptableError", + "httpStatusCode": 406 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/license-list": { + "get": { + "operationId": "getLicenseList", + "description": "Get a sorted list of license ID's, matching the provided filters", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category (must be licensing)", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "List of licenses", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "data": [] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/package-managers": { + "get": { + "operationId": "getIssuePackageManagers", + "description": "Get the set of unique package managers associated with current issues", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "status", + "description": "Issue status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Unique package managers associated with current issues", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "packageManagers": [] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/cwes": { + "get": { + "operationId": "getIssueCWEs", + "description": "Get the set of unique CWEs associated with current issues", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "status", + "description": "Issue status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "teamId[]", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Unique CWEs associated with current issues", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "cwes": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "packageManagers": [] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/{issueId}": { + "get": { + "operationId": "getIssue", + "description": "Retrieve a single issue", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "issueId", + "description": "Issue ID", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Vulnerability, licensing, or quality issue response", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "vulnId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "cve": { + "type": "string" + }, + "cvss": { + "type": "number" + }, + "cvssVector": { + "type": "string", + "description": "The CVSS Vector for the vuln. Prefers the V3 vector if it exists, and falls back to the V2 vector. Is null if neither vector exists." + }, + "severity": { + "type": "string" + }, + "details": { + "type": "string" + }, + "remediation": { + "type": "object", + "properties": { + "partialFix": { + "type": "string" + }, + "partialFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + }, + "completeFix": { + "type": "string" + }, + "completeFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + } + } + }, + "metrics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "cveStatus": { + "type": "string" + }, + "cwes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "published": { + "type": "string", + "format": "date-time" + }, + "affectedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "patchedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "references": { + "type": "array", + "items": { + "type": "string" + } + }, + "exploitability": { + "type": "string", + "enum": [ + "UNKNOWN", + "POC", + "MATURE" + ] + }, + "epss": { + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "percentile": { + "type": "number" + } + } + }, + "customRiskScore": { + "description": "Optional custom risk score for the vulnerability, only present\nwhen the Custom Risk Scores feature is enabled for the organization.\nNot available for global scope queries.\n", + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "reason": { + "type": "string", + "nullable": true + }, + "createdBy": { + "type": "string" + }, + "updatedBy": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + } + } + }, + { + "type": "object", + "properties": { + "source": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "isCorrected": { + "type": "boolean" + } + } + } + ] + } + } + } + ] + }, + { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "license": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "source": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "isCorrected": { + "type": "boolean" + } + } + } + ] + } + } + } + ] + }, + { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "qualityRule": { + "type": "object", + "properties": { + "ruleId": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "notes": { + "type": [ + "string", + "null" + ] + }, + "dependencyOutdatedType": { + "type": [ + "string", + "null" + ], + "enum": [ + "FALLBACK", + "SEMVER" + ] + }, + "dependencyOutdatedVersionPart": { + "type": [ + "string", + "null" + ], + "enum": [ + "MAJOR", + "PATCH", + "MINOR" + ] + }, + "dependencyOutdatedVersionDiff": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterName": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterVersionType": { + "type": [ + "string", + "null" + ], + "enum": [ + "RANGE", + "LESS", + "EQUAL", + "GREATER", + "ALL" + ] + }, + "dependencyFilterStartVersion": { + "type": "string" + }, + "dependencyFilterEndVersion": { + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "packageProjectLocator": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + }, + { + "type": "object", + "properties": { + "source": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "isCorrected": { + "type": "boolean" + } + } + } + ] + } + } + } + ] + } + ] + }, + "examples": { + "vulnIssue": { + "value": { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": true + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "1.15.4", + "completeFix": "1.16.0", + "partialFixDistance": "PATCH", + "completeFixDistance": "MAJOR" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + }, + "vulnIssueWithUnableToCalculateVersions": { + "value": { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": false + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "UNABLE_TO_CALCULATE", + "completeFix": "UNABLE_TO_CALCULATE" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + }, + "vulnIssueWithNoSafeVersions": { + "value": { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": false + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "NO_SAFE_VERSION", + "completeFix": "NO_SAFE_VERSION" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + }, + "licensingIssue": { + "value": { + "id": 144, + "createdAt": "2023-07-13T19:22:16.546Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": true + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "policy_flag", + "license": "unknown" + } + }, + "qualityIssue": { + "value": { + "id": 196, + "createdAt": "2023-07-13T19:22:16.546Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm" + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "blacklisted_dependency", + "qualityRule": { + "ruleId": 6538966, + "type": "blacklisted_dependency", + "notes": "Major difference of 3 or more", + "dependencyOutdatedType": "FALLBACK", + "dependencyOutdatedVersionPart": "PATCH", + "dependencyOutdatedVersionDiff": "20", + "dependencyFilterName": "react", + "dependencyFilterVersionType": "ALL", + "dependencyFilterStartVersion": "4.17.12", + "dependencyFilterEndVersion": "4.0.0", + "enabled": true, + "packageProjectLocator": "npm+react", + "createdAt": "2023-05-31T18:19:08.967Z", + "updatedAt": "2023-05-31T18:19:08.967Z" + }, + "latestVersion": "npm+lodash$4.17.21" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Issue Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Issue not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/{issueId}/disputes": { + "post": { + "operationId": "createIssueDispute", + "description": "Creates an issue dispute. For now it only supports licensing issues.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "issueId", + "in": "path", + "description": "ID of the issue that is being disputed.", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "required": true, + "description": "The reason why this issue is being disputed.", + "enum": [ + "INCORRECT_DEPENDENCY_VERSION_REPORTED", + "LICENSE_DETECTION_FALSE_POSITIVE", + "MULTI_OR_DUAL_LICENSED" + ] + }, + "comment": { + "description": "Any additional information that is important for this dispute.", + "type": "string" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "The created dispute.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "createdBy": { + "type": "number" + }, + "createdAt": { + "type": "string", + "format": "date" + }, + "licenseId": { + "type": "string" + }, + "disputedIssueId": { + "type": "number" + }, + "reason": { + "type": "string", + "description": "The reason why this issue is being disputed.", + "enum": [ + "INCORRECT_DEPENDENCY_VERSION_REPORTED", + "LICENSE_DETECTION_FALSE_POSITIVE", + "MULTI_OR_DUAL_LICENSED" + ] + }, + "comment": { + "type": "string" + }, + "resolvedAt": { + "type": "string", + "format": "date" + }, + "resolvedBy": { + "type": "number" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/{issueId}/affected-projects": { + "get": { + "operationId": "getIssueAffectedProjects", + "description": "Retrieves a list of affected projects for a given issue.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "issueId", + "description": "Issue ID", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Affected project list", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Project ID" + }, + "revisionId": { + "type": "string", + "description": "Revision ID" + }, + "title": { + "type": "string", + "description": "Project title" + }, + "status": { + "type": "string", + "description": "Project status" + }, + "branch": { + "type": "string", + "description": "Default or Release Group Project's revision branch" + }, + "jiraTicketId": { + "type": "string", + "description": "Jira ticket ID" + }, + "jiraTicketURL": { + "type": "string", + "description": "Jira ticket URL" + }, + "type": { + "type": "string", + "enum": [ + "jira" + ], + "description": "The type of ticket export" + }, + "concludedLicenses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The concluded licenses for the project" + } + } + } + }, + "examples": { + "affectedProject": { + "value": [ + { + "id": "custom+1/TEST", + "revisionId": "custom+1/TEST$123", + "title": "TEST", + "status": "active", + "branch": "master", + "jiraTicketId": "TEST-123", + "jiraTicketURL": "https://test.atlassian.net/browse/TEST-123", + "type": "jira", + "concludedLicenses": [ + "MIT", + "Apache-2.0" + ] + } + ] + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues": { + "get": { + "operationId": "getIssues", + "description": "Retrieve multiple issues", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "csv", + "description": "Retrieves issues as a CSV", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDirectDependencyOriginPaths", + "description": "Include origin paths for the direct dependency responsible for\nincluding the revision(s) affected by this issue\n", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "status", + "description": "Issue status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "ids[]", + "description": "Filter by specific issue IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + { + "name": "filter[revisionIds][]", + "description": "Filter by specific revision IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[search]", + "description": "Filter by package name or CVE (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filter[depths][]", + "description": "Filter by issue depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "deep" + ] + } + } + }, + { + "name": "filter[ticketed][]", + "description": "Filter by ticketed status. Only available to premium users.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + } + } + }, + { + "name": "filter[containerLayers][]", + "description": "Filter by container layer", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + } + }, + { + "name": "filter[type][]", + "description": "Filter by licensing issue type (when category is \"licensing\") or quality issue type (when category is \"quality\")\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency" + ] + } + } + ] + } + }, + { + "name": "filter[packageManagers][]", + "description": "Filter by specific package managers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[cwes][]", + "description": "Filter by specific CWE identifiers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[projectLabels][]", + "description": "Filter by specific project labels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[identification][]", + "description": "Filter by license identification (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + } + } + }, + { + "name": "filter[severity][]", + "description": "Filter by vuln severity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "filter[severitySource][]", + "description": "Filter by severity source (when category is \"vulnerability\"). Use 'standard' to filter by CVSS score, 'custom' to filter by custom risk score. When both are provided, issues matching either source are returned. Defaults to 'standard' when not provided. Custom risk score filtering requires the Custom Risk Scores feature to be enabled and a non-global scope.\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "standard", + "custom" + ] + } + } + }, + { + "name": "filter[foundBefore]", + "description": "Include only issues found on before a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[foundAfter]", + "description": "Include only issues found on after a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[hasFix][]", + "description": "Filter by vuln fixability (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "filter[upgradeDistance][]", + "description": "Filter by vuln upgrade distance (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + } + } + }, + { + "name": "filter[exploitMaturity][]", + "description": "Filter by vuln exploit maturity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + } + } + }, + { + "name": "filter[ignoreReason][]", + "description": "Filter by vuln ignore reason (when category is \"vulnerability\") This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + } + } + }, + { + "name": "filter[epss]", + "description": "Filter by epss 'score' or 'percentile'. All fields are required. Only available to premium users.", + "in": "query", + "style": "deepObject", + "explode": true, + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "score", + "percentile" + ] + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + } + }, + "examples": { + "filterByScore": { + "value": { + "type": "score", + "min": 0.01, + "max": 0.25 + }, + "summary": "Filter to issues with a score between 0.1 and 0.25 (inclusive)" + }, + "filterByPercentile": { + "value": { + "type": "percentile", + "min": 0.85, + "max": 1 + }, + "summary": "Filter to issues above the 85th percentile (inclusive)" + } + } + }, + { + "name": "filter[confidence][]", + "description": "Filter issues by their binary dependency confidence level(s)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "High", + "Medium", + "Low", + "Unknown" + ] + } + } + }, + { + "name": "filter[issueSource][]", + "description": "Filter by issue source. Use 'dependency' and 'snippet' to filter by whether the issue comes from a dependency or a code snippet. When the vendored dependency detection feature is enabled, use 'managed-dependency' and 'vendored-dependency' to filter dependency issues by whether the dependency is managed or vendored.\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "dependency", + "snippet" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed-dependency", + "vendored-dependency", + "snippet" + ] + } + } + ] + } + }, + { + "name": "sort", + "description": "Sort by package name, when the issue was created, or severity (when category is \"vulnerability\")\n", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "created_at_asc", + "created_at_desc", + "severity_asc", + "severity_desc", + "epss_asc", + "epss_desc" + ] + } + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 20 + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Vulnerability, licensing, or quality issues response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "issues": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "vulnId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "cve": { + "type": "string" + }, + "cvss": { + "type": "number" + }, + "cvssVector": { + "type": "string", + "description": "The CVSS Vector for the vuln. Prefers the V3 vector if it exists, and falls back to the V2 vector. Is null if neither vector exists." + }, + "severity": { + "type": "string" + }, + "details": { + "type": "string" + }, + "remediation": { + "type": "object", + "properties": { + "partialFix": { + "type": "string" + }, + "partialFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + }, + "completeFix": { + "type": "string" + }, + "completeFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + } + } + }, + "metrics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "cveStatus": { + "type": "string" + }, + "cwes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "published": { + "type": "string", + "format": "date-time" + }, + "affectedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "patchedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "references": { + "type": "array", + "items": { + "type": "string" + } + }, + "exploitability": { + "type": "string", + "enum": [ + "UNKNOWN", + "POC", + "MATURE" + ] + }, + "epss": { + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "percentile": { + "type": "number" + } + } + }, + "customRiskScore": { + "description": "Optional custom risk score for the vulnerability, only present\nwhen the Custom Risk Scores feature is enabled for the organization.\nNot available for global scope queries.\n", + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "reason": { + "type": "string", + "nullable": true + }, + "createdBy": { + "type": "string" + }, + "updatedBy": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + } + } + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "license": { + "type": "string" + } + } + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "qualityRule": { + "type": "object", + "properties": { + "ruleId": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "notes": { + "type": [ + "string", + "null" + ] + }, + "dependencyOutdatedType": { + "type": [ + "string", + "null" + ], + "enum": [ + "FALLBACK", + "SEMVER" + ] + }, + "dependencyOutdatedVersionPart": { + "type": [ + "string", + "null" + ], + "enum": [ + "MAJOR", + "PATCH", + "MINOR" + ] + }, + "dependencyOutdatedVersionDiff": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterName": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterVersionType": { + "type": [ + "string", + "null" + ], + "enum": [ + "RANGE", + "LESS", + "EQUAL", + "GREATER", + "ALL" + ] + }, + "dependencyFilterStartVersion": { + "type": "string" + }, + "dependencyFilterEndVersion": { + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "packageProjectLocator": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + } + ] + } + } + }, + "examples": { + "vulnIssues": { + "value": { + "issues": [ + { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": false + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "1.15.4", + "completeFix": "1.16.0", + "partialFixDistance": "PATCH", + "completeFixDistance": "MAJOR" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + ] + } + }, + "vulnIssuesWithUnableToCalculateVersions": { + "value": { + "issues": [ + { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": false + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "UNABLE_TO_CALCULATE", + "completeFix": "UNABLE_TO_CALCULATE" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + ] + } + }, + "vulnIssuesWithNoSafeVersions": { + "value": { + "issues": [ + { + "id": 27, + "createdAt": "2023-01-19T22:38:02.961Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm", + "isCorrected": false + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "vulnerability", + "vulnId": "CVE-2018-16487_npm+lodash", + "title": "General Vulnerability", + "cve": "CVE-2018-16487", + "cvss": 9.8, + "cvssVector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "severity": "critical", + "details": "A prototype pollution vulnerability was found in lodash <4.17.11 where the functions merge, mergeWith, and defaultsDeep can be tricked into adding or modifying properties of Object.prototype.", + "remediation": { + "partialFix": "NO_SAFE_VERSION", + "completeFix": "NO_SAFE_VERSION" + }, + "metrics": [ + { + "name": "Attack Vector", + "value": "Network" + } + ], + "cveStatus": "COMPLETED", + "cwes": [ + "CWE-254" + ], + "published": "2018-09-04T00:00:00.000Z", + "affectedVersionRanges": [ + "<4.17.11" + ], + "patchedVersionRanges": [ + "4.17.11" + ], + "references": [ + "https://nvd.nist.gov/vuln/detail/CVE-2018-16487" + ], + "epss": { + "score": 0.1234, + "percentile": 0.42 + }, + "exploitability": "MATURE" + } + ] + } + }, + "licensingIssues": { + "value": { + "issues": [ + { + "id": 144, + "createdAt": "2023-07-13T19:22:16.546Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm" + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "policy_flag", + "license": "unknown" + } + ] + } + }, + "qualityIssues": { + "value": { + "issues": [ + { + "id": 196, + "createdAt": "2023-07-13T19:22:16.546Z", + "source": { + "id": "npm+lodash$4.2.0", + "name": "lodash", + "url": "https://www.npmjs.com/package/lodash", + "version": "4.2.0", + "packageManager": "npm" + }, + "depths": { + "direct": 3, + "deep": 0 + }, + "containerLayers": { + "base": 1, + "other": 1 + }, + "statuses": { + "active": 2, + "ignored": 1 + }, + "projects": [ + { + "id": "custom+1/TEST", + "status": "active", + "depth": 1, + "title": "TEST", + "scannedAt": "2023-07-12T01:22:12.669+00:00", + "analyzedAt": "2023-07-12T01:12:36.003+00:00", + "url": "http://example.com/projectlink", + "firstFoundAt": "2023-07-12T01:12:36.003+00:00" + } + ], + "type": "blacklisted_dependency", + "qualityRule": { + "ruleId": 6538966, + "type": "blacklisted_dependency", + "notes": "Major difference of 3 or more", + "dependencyOutdatedType": "FALLBACK", + "dependencyOutdatedVersionPart": "PATCH", + "dependencyOutdatedVersionDiff": "20", + "dependencyFilterName": "react", + "dependencyFilterVersionType": "ALL", + "dependencyFilterStartVersion": "4.17.12", + "dependencyFilterEndVersion": "4.0.0", + "enabled": true, + "packageProjectLocator": "npm+react", + "createdAt": "2023-05-31T18:19:08.967Z", + "updatedAt": "2023-05-31T18:19:08.967Z" + } + } + ] + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "issues": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "vulnId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "cve": { + "type": "string" + }, + "cvss": { + "type": "number" + }, + "cvssVector": { + "type": "string", + "description": "The CVSS Vector for the vuln. Prefers the V3 vector if it exists, and falls back to the V2 vector. Is null if neither vector exists." + }, + "severity": { + "type": "string" + }, + "details": { + "type": "string" + }, + "remediation": { + "type": "object", + "properties": { + "partialFix": { + "type": "string" + }, + "partialFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + }, + "completeFix": { + "type": "string" + }, + "completeFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + } + } + }, + "metrics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "cveStatus": { + "type": "string" + }, + "cwes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "published": { + "type": "string", + "format": "date-time" + }, + "affectedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "patchedVersionRanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "references": { + "type": "array", + "items": { + "type": "string" + } + }, + "exploitability": { + "type": "string", + "enum": [ + "UNKNOWN", + "POC", + "MATURE" + ] + }, + "epss": { + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "percentile": { + "type": "number" + } + } + }, + "customRiskScore": { + "description": "Optional custom risk score for the vulnerability, only present\nwhen the Custom Risk Scores feature is enabled for the organization.\nNot available for global scope queries.\n", + "type": "object", + "properties": { + "score": { + "type": "number" + }, + "reason": { + "type": "string", + "nullable": true + }, + "createdBy": { + "type": "string" + }, + "updatedBy": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + } + } + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "license": { + "type": "string" + } + } + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + }, + "packageManager": { + "type": "string" + } + } + }, + "depths": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "deep": { + "type": "integer" + } + } + }, + "containerLayers": { + "type": "object", + "properties": { + "base": { + "type": "integer" + }, + "other": { + "type": "integer" + } + } + }, + "statuses": { + "type": "object", + "properties": { + "active": { + "type": "integer" + }, + "ignored": { + "type": "integer" + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "depth": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "scannedAt": { + "type": "string", + "format": "date-time" + }, + "analyzedAt": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string", + "description": "A link to the project the issue is from." + }, + "originPaths": { + "description": "Optional array of direct dependency origin paths, only present\nwhen includeDirectDependencyOriginPaths=true is supplied as a URL param.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "firstFoundAt": { + "type": "string", + "format": "date-time", + "description": "The date when the issue was first found for this project or release group." + }, + "defaultBranch": { + "type": "string", + "description": "The default branch of the project." + }, + "latest": { + "type": "boolean", + "description": "Whether this issue is present in the most recent scan of the project. If false, the issue may be considered remediated." + }, + "revisionId": { + "type": "string", + "description": "The ID of the revision that is affected by this issue." + }, + "revisionScanId": { + "type": "number", + "description": "The ID of the revision scan associated with this issue." + } + } + } + }, + "type": { + "type": "string" + }, + "qualityRule": { + "type": "object", + "properties": { + "ruleId": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "notes": { + "type": [ + "string", + "null" + ] + }, + "dependencyOutdatedType": { + "type": [ + "string", + "null" + ], + "enum": [ + "FALLBACK", + "SEMVER" + ] + }, + "dependencyOutdatedVersionPart": { + "type": [ + "string", + "null" + ], + "enum": [ + "MAJOR", + "PATCH", + "MINOR" + ] + }, + "dependencyOutdatedVersionDiff": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterName": { + "type": [ + "string", + "null" + ] + }, + "dependencyFilterVersionType": { + "type": [ + "string", + "null" + ], + "enum": [ + "RANGE", + "LESS", + "EQUAL", + "GREATER", + "ALL" + ] + }, + "dependencyFilterStartVersion": { + "type": "string" + }, + "dependencyFilterEndVersion": { + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "packageProjectLocator": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + } + ] + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "issues": [] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "406": { + "description": "Not Acceptable", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Accept": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2015, + "message": "Invalid accept:", + "name": "NotAcceptableError", + "httpStatusCode": 406 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateIssues", + "description": "Apply actions to the current selection of issues or set of applied filters. Note that Issue Exports are only allowed for premium users.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "status", + "description": "Issue status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "ids[]", + "description": "Filter by specific issue IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + { + "name": "filter[revisionIds][]", + "description": "Filter by specific revision IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[search]", + "description": "Filter by package name or CVE (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filter[depths][]", + "description": "Filter by issue depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "deep" + ] + } + } + }, + { + "name": "filter[ticketed][]", + "description": "Filter by ticketed status. Only available to premium users.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + } + } + }, + { + "name": "filter[containerLayers][]", + "description": "Filter by container layer", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + } + }, + { + "name": "filter[type][]", + "description": "Filter by licensing issue type (when category is \"licensing\") or quality issue type (when category is \"quality\")\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency" + ] + } + } + ] + } + }, + { + "name": "filter[packageManagers][]", + "description": "Filter by specific package managers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[projectLabels][]", + "description": "Filter by specific project labels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[identification][]", + "description": "Filter by license identification (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + } + } + }, + { + "name": "filter[severity][]", + "description": "Filter by vuln severity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "filter[severitySource][]", + "description": "Filter by severity source (when category is \"vulnerability\"). Use 'standard' to filter by CVSS score, 'custom' to filter by custom risk score. When both are provided, issues matching either source are returned. Defaults to 'standard' when not provided. Custom risk score filtering requires the Custom Risk Scores feature to be enabled and a non-global scope.\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "standard", + "custom" + ] + } + } + }, + { + "name": "filter[foundAfter]", + "description": "Include only issues found on after a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[hasFix][]", + "description": "Filter by vuln fixability (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "filter[upgradeDistance][]", + "description": "Filter by vuln upgrade distance (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + } + } + }, + { + "name": "filter[exploitMaturity][]", + "description": "Filter by vuln exploit maturity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + } + } + }, + { + "name": "filter[ignoreReason][]", + "description": "Filter by vuln ignore reason (when category is \"vulnerability\") This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + } + } + }, + { + "name": "filter[licenses][]", + "description": "Filter by issues affected by a set of license ID's (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[confidence][]", + "description": "Filter issues by their binary dependency confidence level(s)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "High", + "Medium", + "Low", + "Unknown" + ] + } + } + }, + { + "name": "filter[issueSource][]", + "description": "Filter by issue source. Use 'dependency' and 'snippet' to filter by whether the issue comes from a dependency or a code snippet. When the vendored dependency detection feature is enabled, use 'managed-dependency' and 'vendored-dependency' to filter dependency issues by whether the dependency is managed or vendored.\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "dependency", + "snippet" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed-dependency", + "vendored-dependency", + "snippet" + ] + } + } + ] + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ignore" + ] + }, + "notes": { + "type": "string" + }, + "reason": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "export" + ] + }, + "ticket": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "required": true, + "enum": [ + "jira" + ] + }, + "title": { + "type": "string", + "required": true + }, + "description": { + "type": "string", + "required": true + }, + "uniqueTickets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "content": { + "type": "string" + }, + "issueId": { + "type": "number" + } + } + } + }, + "trackerId": { + "type": "string" + }, + "jiraId": { + "type": "string" + }, + "issueType": { + "type": "string" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, + "customFields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fieldId": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "components": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + } + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "custom" + ], + "required": true + }, + "url": { + "type": "string", + "required": true + }, + "comment": { + "type": "string" + } + } + } + ] + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "unlink" + ] + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "unignore" + ] + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "issueException" + ] + }, + "packageScope": { + "type": "string", + "enum": [ + "SELECTED_VERSION", + "ALL_VERSIONS" + ] + }, + "ignoreScope": { + "type": "string", + "enum": [ + "ORGANIZATION", + "POLICY", + "PROJECT", + "RELEASE_GROUP", + "PROJECT_AND_RELEASE_GROUPS" + ] + }, + "expiresAfter": { + "type": "string", + "format": "date", + "nullable": true, + "description": "The UTC date after which the exception will expire. If not provided, the exception will never expire.\n" + }, + "notes": { + "description": "This is a free-form field for users to provide additional context for the exception. This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "type": "string" + }, + "reason": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + }, + "licenseId": { + "type": "string", + "description": "Set a license ID to create exceptions for a specific license ID.\n" + } + } + } + ] + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Count of affected issues", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "User has no email": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "user: X does not have a valid email: Y", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "User doesn't have permission for this issue": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "attempting to modify projects without permission", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Organization is not premium": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User not permissioned for feature. Feature requires \"premium\" subscription access level.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/v2/issues/revisions": { + "get": { + "operationId": "getIssuesByRevision", + "description": "Retrieve issue metadata that is grouped by revision", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "category", + "description": "Issue category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "status", + "description": "Issue status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + } + }, + { + "name": "scope[type]", + "description": "Scope of issues to view / update", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "global", + "project", + "releaseGroup" + ] + } + }, + { + "name": "scope[id]", + "description": "Project or release group ID (required when scope[type] is \"project\" or \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revision]", + "description": "Revision ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[revisionScanId]", + "description": "Revision scan ID (when scope[type] is \"project\")", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "scope[release]", + "description": "Release group ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[releaseScanId]", + "description": "Release scan ID (when scope[type] is \"releaseGroup\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][revision]", + "description": "The revision ID to compare issues with. Only available for Project Scope.", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope[compareTo][changeStatus]", + "description": "The status of issues to fetch when comparing issues. - New issues are present in the current revision but not in the comparison revision. - Remediated issues are present in the comparison revision but not in the current revision. - Unchanged issues are present in both revisions. Only available for Project Scope.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "new", + "remediated", + "unchanged" + ] + } + }, + { + "name": "ids[]", + "description": "Filter by specific issue IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + { + "name": "filter[revisionIds][]", + "description": "Filter by specific revision IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[search]", + "description": "Filter by package name or CVE (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filter[depths][]", + "description": "Filter by issue depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "deep" + ] + } + } + }, + { + "name": "filter[ticketed][]", + "description": "Filter by ticketed status. Only available to premium users.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + } + } + }, + { + "name": "filter[containerLayers][]", + "description": "Filter by container layer", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + } + }, + { + "name": "filter[type][]", + "description": "Filter by licensing issue type (when category is \"licensing\") or quality issue type (when category is \"quality\")\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency" + ] + } + } + ] + } + }, + { + "name": "filter[packageManagers][]", + "description": "Filter by specific package managers", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[projectLabels][]", + "description": "Filter by specific project labels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[identification][]", + "description": "Filter by license identification (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + } + } + }, + { + "name": "filter[severity][]", + "description": "Filter by vuln severity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "filter[foundAfter]", + "description": "Include only issues found on after a given ISO timestamp. Only available to premium users", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter[hasFix][]", + "description": "Filter by vuln fixability (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "filter[upgradeDistance][]", + "description": "Filter by vuln upgrade distance (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + } + } + }, + { + "name": "filter[exploitMaturity][]", + "description": "Filter by vuln exploit maturity (when category is \"vulnerability\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + } + } + }, + { + "name": "filter[ignoreReason][]", + "description": "Filter by vuln ignore reason (when category is \"vulnerability\") This value appears in the vulnerabilities.analysis.detail field in CycloneDX SBOM reports\n", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + } + } + }, + { + "name": "filter[licenses][]", + "description": "Filter by issues affected by a set of license ID's (when category is \"licensing\")", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "filter[issueSource][]", + "description": "Filter by issue source. Use 'dependency' and 'snippet' to filter by whether the issue comes from a dependency or a code snippet. When the vendored dependency detection feature is enabled, use 'managed-dependency' and 'vendored-dependency' to filter dependency issues by whether the dependency is managed or vendored.\n", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "dependency", + "snippet" + ] + } + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed-dependency", + "vendored-dependency", + "snippet" + ] + } + } + ] + } + }, + { + "name": "sort", + "description": "Sort by package name, when the issue was created, or total number of issues\n", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "created_at_asc", + "created_at_desc", + "issue_count_asc", + "issue_count_desc", + "epss_asc", + "epss_desc" + ] + } + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 20 + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Issue revisions response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "revisions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "revisionId": { + "type": "string" + }, + "dependencyName": { + "type": "string" + }, + "issueCount": { + "type": "integer" + }, + "projectCount": { + "type": "integer" + }, + "jiraTicketCount": { + "type": "integer" + }, + "depth": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "transitive": { + "type": "integer" + } + } + }, + "type": { + "oneOf": [ + { + "type": "object", + "properties": { + "policy_conflict": { + "type": "integer" + }, + "policy_flag": { + "type": "integer" + }, + "unlicensed_dependency": { + "type": "integer" + } + } + }, + { + "type": "object", + "properties": { + "outdated_dependency": { + "type": "integer" + }, + "blacklisted_dependency": { + "type": "integer" + } + } + }, + { + "type": "object", + "properties": { + "critical": { + "type": "integer" + }, + "high": { + "type": "integer" + }, + "medium": { + "type": "integer" + }, + "low": { + "type": "integer" + }, + "unknown": { + "type": "integer" + } + } + } + ] + } + } + } + } + } + } + } + } + }, + "202": { + "description": "Empty results with a message indicating the scoped project's build status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "revisions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "revisionId": { + "type": "string" + }, + "dependencyName": { + "type": "string" + }, + "issueCount": { + "type": "integer" + }, + "projectCount": { + "type": "integer" + }, + "jiraTicketCount": { + "type": "integer" + }, + "depth": { + "type": "object", + "properties": { + "direct": { + "type": "integer" + }, + "transitive": { + "type": "integer" + } + } + }, + "type": { + "oneOf": [ + { + "type": "object", + "properties": { + "policy_conflict": { + "type": "integer" + }, + "policy_flag": { + "type": "integer" + }, + "unlicensed_dependency": { + "type": "integer" + } + } + }, + { + "type": "object", + "properties": { + "outdated_dependency": { + "type": "integer" + }, + "blacklisted_dependency": { + "type": "integer" + } + } + }, + { + "type": "object", + "properties": { + "critical": { + "type": "integer" + }, + "high": { + "type": "integer" + }, + "medium": { + "type": "integer" + }, + "low": { + "type": "integer" + }, + "unknown": { + "type": "integer" + } + } + } + ] + } + } + } + } + } + }, + "examples": { + "analyzing": { + "value": { + "message": "analysis in-progress", + "revisions": [] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/csv/global": { + "get": { + "operationId": "getGlobalIssuesCSV", + "description": "Download the global issues report (CSV) or submit for background processing", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "email", + "description": "When provided, we will submit the report for background processing and deliver via email when ready. Otherwise the report will be streamed via API", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "CSV report (as a zip file) or background task metadata", + "content": { + "application/octet-stream": { + "schema": { + "description": "default behavior for this endpoint is to stream a CSV report as a zip file", + "type": "string", + "format": "binary" + } + }, + "application/json": { + "schema": { + "description": "When an email is provided in the query parameter, we will queue the Report as a background task, and return information for the given job", + "type": "object", + "properties": { + "task": { + "type": "string" + }, + "jobToken": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/issues/exceptions": { + "get": { + "operationId": "getIssueExceptions", + "description": "List issue ignore rules.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "filters[category]", + "description": "Exception category", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "filters[projectId]", + "description": "Exception project ID", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "filters[releaseGroupId]", + "description": "Exception release group ID", + "in": "query", + "schema": { + "type": "integer" + } + }, + { + "name": "search", + "in": "query", + "description": "Search term (search by created by, revision, note, or package)", + "schema": { + "type": "string" + } + }, + { + "name": "sortBy", + "in": "query", + "description": "Sort by field (id, package, created by, and ignore scope)", + "schema": { + "type": "string", + "enum": [ + "id", + "package", + "created_by", + "scope" + ] + } + }, + { + "name": "orderBy", + "in": "query", + "description": "Sort order", + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 20 + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "List of issue ignore rules", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "exceptions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "ignoreScope": { + "type": "string", + "enum": [ + "ORGANIZATION", + "POLICY", + "PROJECT", + "RELEASE_GROUP", + "PROJECT_AND_RELEASE_GROUPS" + ] + }, + "packageScope": { + "type": "string", + "enum": [ + "SELECTED_VERSION", + "ALL_VERSIONS" + ] + }, + "issueCategory": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "exceptionUserProjectId": { + "type": "string" + }, + "exceptionUserReleaseGroupId": { + "type": "integer" + }, + "exceptionUserPolicyId": { + "type": "integer" + }, + "projectTitle": { + "type": "string" + }, + "dependencyProjectLocator": { + "type": "string" + }, + "dependencyRevisionLocator": { + "type": "string" + }, + "dependencyTitle": { + "type": "string" + }, + "condition": { + "type": "object" + }, + "exceptionTitle": { + "type": "string" + }, + "note": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "policyTitle": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + } + }, + "total": { + "type": "integer" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Non Licensing Policy ID Filtering": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Cannot filter by Policy ID for Security exceptions", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteIssueExceptions", + "description": "Delete issue ignore rules.", + "tags": [ + "Issues" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "all" + ] + }, + "filters": { + "type": "object", + "properties": { + "policyId": { + "type": "integer", + "required": false + }, + "projectId": { + "type": "string", + "required": false + }, + "releaseGroupId": { + "type": "integer", + "required": false + }, + "category": { + "type": "string", + "enum": [ + "licensing" + ] + } + } + } + } + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "idList" + ] + }, + "value": { + "type": "array", + "items": { + "type": "integer" + } + } + } + } + ] + }, + "examples": { + "Remove All": { + "value": { + "kind": "all", + "filters": { + "policyId": null, + "projectId": "custom+1/project", + "releaseGroupId": null + } + } + }, + "Remove by ID List": { + "value": { + "kind": "idList", + "value": [ + 1, + 2 + ] + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Count of deleted issue ignore rules", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No exceptions found for deletion": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No exceptions found for the provided IDs.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Improper user permissions": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No project ID provided for project and release groups level exception.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/v2/issues/exceptions/{id}": { + "get": { + "operationId": "getIssueException", + "description": "Get a single issue ignore rule by ID.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "id", + "description": "ID of the issue exception", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Issue exception details", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "ignoreScope": { + "type": "string", + "enum": [ + "ORGANIZATION", + "POLICY", + "PROJECT", + "RELEASE_GROUP", + "PROJECT_AND_RELEASE_GROUPS" + ] + }, + "packageScope": { + "type": "string", + "enum": [ + "SELECTED_VERSION", + "ALL_VERSIONS" + ] + }, + "issueCategory": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "exceptionUserProjectId": { + "type": "string", + "nullable": true + }, + "exceptionUserReleaseGroupId": { + "type": "integer", + "nullable": true + }, + "exceptionUserPolicyId": { + "type": "integer", + "nullable": true + }, + "projectTitle": { + "type": "string", + "nullable": true + }, + "dependencyProjectLocator": { + "type": "string", + "nullable": true + }, + "dependencyRevisionLocator": { + "type": "string", + "nullable": true + }, + "dependencyTitle": { + "type": "string", + "nullable": true + }, + "exceptionTitle": { + "type": "string", + "nullable": true + }, + "note": { + "type": "string", + "nullable": true + }, + "createdBy": { + "type": "string" + }, + "reason": { + "type": "string", + "nullable": true + }, + "policyTitle": { + "type": "string", + "nullable": true + }, + "packageLabel": { + "type": "string", + "nullable": true + }, + "expiresAfter": { + "type": "string", + "nullable": true + }, + "isExpired": { + "type": "boolean" + }, + "createdAt": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Non-numeric id": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Exception ID must be a number.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "User does not have permission to view this resource": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Exception not found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Exception with id 123 not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "extendIssueException", + "summary": "Extend an issue exception expiration date", + "description": "Updates the expiration date for an existing issue exception.\nPass null to set the exception to never expire (unset the expiration date).\nRequires premium subscription.\n", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "id", + "description": "ID of the issue exception to extend", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "expiresAfter": { + "type": "string", + "format": "date", + "nullable": true, + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "description": "Expiration date in YYYY-MM-DD format, or null to never expire", + "example": "2025-12-31" + } + }, + "required": [ + "expiresAfter" + ] + }, + "examples": { + "Set expiration date": { + "value": { + "expiresAfter": "2025-12-31" + } + }, + "Remove expiration (never expires)": { + "value": { + "expiresAfter": null + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "204": { + "description": "Exception expiration successfully updated" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid date format": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "An expires after in YYYY-MM-DD format or null is required.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid exception ID": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Exception ID must be a number.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission for project exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to resolve Licensing issues for project: custom+1/project.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "No permission for policy exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to edit policies.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "No permission for release group exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to resolve Licensing issues for release group: 123.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Exception not found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Exception with id 123 not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteIssueException", + "description": "Delete an issue ignore rule.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "id", + "description": "ID of the issue exception to be deleted", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Number of issues that were ignored by this exception", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Non-numeric id": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Exception ID must be a number.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No policy ID provided for policy exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No policy ID provided for policy level exception.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No project ID provided for project exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No project ID provided for project level exception.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No Release Group ID provided for Release Group exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No release group ID provided for release group level exception.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No Project ID provided for Project + Release Group exception": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No project ID provided for project and release groups level exception.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Exception does not belong to Organization": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "Exception does not belong to organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "User does not have permission to edit policies": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to edit policies.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "User does not have permission to resolve issues in project": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to resolve Licensing issues for project: X", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "User does not have permission to resolve issues in release group": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to resolve Licensing issues for all release groups", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/issue-filters": { + "get": { + "summary": "List out saved filters", + "description": "This endpoint returns a list of saved filters for the organization. The filters are categorized into licensing, vulnerability, and quality -- only the requested category of filters will be returned.\n", + "operationId": "listSavedFilters", + "tags": [ + "Issue Filters" + ], + "parameters": [ + { + "name": "category", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "description": "The category of the issue filters." + } + ], + "responses": { + "200": { + "description": "A list of saved filters", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "filter": { + "type": "object", + "description": "A JSON object representing the specific filter criteria.", + "additionalProperties": { + "type": "json" + } + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + } + }, + "403": { + "description": "Authentication failed or not a premium account." + } + } + }, + "post": { + "summary": "Create a saved filter for your organization", + "description": "This endpoint allows you to create a saved filter for your organization.\n", + "operationId": "createSavedFilter", + "tags": [ + "Issue Filters" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "category": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "name": { + "type": "string" + }, + "filter": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + }, + "identification": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "properties": { + "severity": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + }, + "hasFix": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + }, + "upgradeDistance": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + }, + "exploitMaturity": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + }, + "ignoreReason": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + }, + "reachability": { + "type": "string", + "enum": [ + "reachable", + "unknown" + ] + }, + "cwes": { + "type": "array", + "items": { + "type": "string" + } + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency", + "risk_abandonware", + "risk_empty_package", + "risk_native_code" + ] + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + } + ] + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Saved filter created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "filter": { + "type": "object", + "description": "A JSON object representing the specific filter criteria.", + "additionalProperties": { + "type": "json" + } + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + }, + "403": { + "description": "Authentication failed or not a premium account." + } + } + } + }, + "/issue-filters/{filterId}": { + "get": { + "summary": "Get a saved filter by ID", + "description": "Get a saved filter by ID. The filter must be owned by the user's organization.\n", + "operationId": "getSavedFilterById", + "tags": [ + "Issue Filters" + ], + "parameters": [ + { + "name": "filterId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The ID of the saved filter." + } + ], + "responses": { + "200": { + "description": "A saved filter object", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "filter": { + "type": "object", + "description": "A JSON object representing the specific filter criteria.", + "additionalProperties": { + "type": "json" + } + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + }, + "400": { + "description": "Invalid or missing ID." + }, + "403": { + "description": "Authentication failed or not a premium account." + } + } + }, + "put": { + "summary": "Update a saved filter for your organization", + "description": "Update a saved filter for your organization. The filter must be owned by the user's organization.\n", + "operationId": "updateSavedFilter", + "tags": [ + "Issue Filters" + ], + "parameters": [ + { + "name": "filterId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The ID of the saved filter." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "filter": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "policy_conflict", + "policy_flag", + "unlicensed_dependency" + ] + }, + "identification": { + "type": "string", + "enum": [ + "declared", + "discovered" + ] + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "properties": { + "severity": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + }, + "hasFix": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + }, + "upgradeDistance": { + "type": "string", + "enum": [ + "none", + "major", + "minor", + "patch", + "unknown" + ] + }, + "exploitMaturity": { + "type": "string", + "enum": [ + "has_known_exploit", + "no_known_exploit" + ] + }, + "ignoreReason": { + "type": "string", + "description": "Provided reason for ignoring or resolving a security issue. 'Fixed' and 'Under_investigation' map to VEX statuses with the same names. All other values map to the VEX status 'Not Affected'. This value appears in the vulnerabilities.analysis.justification field of CycloneDX SBOM reports.\n", + "enum": [ + "Fixed", + "Under_investigation", + "Vulnerable_code_not_present", + "Vulnerable_code_cannot_be_controlled", + "Component_not_present", + "Vulnerable_code_not_in_execute_path", + "Inline_mitigations_already_exist", + "incorrect_data_found", + "other" + ] + }, + "reachability": { + "type": "string", + "enum": [ + "reachable", + "unknown" + ] + }, + "cwes": { + "type": "array", + "items": { + "type": "string" + } + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "outdated_dependency", + "blacklisted_dependency", + "risk_abandonware", + "risk_empty_package", + "risk_native_code" + ] + }, + "search": { + "type": "string" + }, + "ticketed": { + "type": "string", + "enum": [ + "jira", + "custom", + "has_ticket", + "no_ticket" + ] + }, + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + }, + "projectLabels": { + "type": "array", + "items": { + "type": "string" + } + }, + "revisionIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "containerLayers": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "baseLayer", + "otherLayer" + ] + } + }, + "foundAfter": { + "type": "string", + "format": "date-time" + } + } + } + ] + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Saved filter updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + }, + "filter": { + "type": "object", + "description": "A JSON object representing the specific filter criteria.", + "additionalProperties": { + "type": "json" + } + }, + "sort": { + "type": "string", + "description": "Can be any of the sort options related to issue or revision.", + "enum": [ + "severity_asc", + "severity_desc", + "issue_count_asc", + "issue_count_desc", + "created_at_asc", + "created_at_desc", + "package_asc", + "package_desc", + "epss_asc", + "epss_desc" + ] + }, + "group": { + "type": "string", + "enum": [ + "issue", + "revision" + ] + } + } + } + } + } + }, + "400": { + "description": "Invalid or missing ID." + }, + "403": { + "description": "Authentication failed or not a premium account." + } + } + }, + "delete": { + "summary": "Delete a saved filter by ID", + "description": "Delete a saved filter by ID. The filter must be owned by the user's organization.\n", + "operationId": "deleteSavedFilter", + "tags": [ + "Issue Filters" + ], + "parameters": [ + { + "name": "filterId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The ID of the saved filter." + } + ], + "responses": { + "200": { + "description": "Saved filter deleted successfully" + }, + "400": { + "description": "Invalid or missing ID." + }, + "403": { + "description": "Authentication failed or not a premium account." + } + } + } + }, + "/issue_counts": { + "get": { + "operationId": "getIssueCounts", + "description": "Fetch the daily issue counts based on provided filters.", + "tags": [ + "Issue Overview" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "start", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to 30 days before the end date.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "end", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to the current date and time.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "The project labels to filter Issue Overview data to.", + "schema": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + } + }, + { + "name": "category", + "description": "The issue category to filter Issue Overview data to. If no category is chosen, it will fetch data for all issue categories.", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "projectId", + "description": "The specific project ID to filter Issue Overview data to.", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + } + ], + "responses": { + "200": { + "description": "Okay", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "counts", + "totalProjects" + ], + "properties": { + "counts": { + "type": "object", + "description": "An array of daily issue count summaries.", + "properties": { + "date": { + "type": "string", + "format": "date-time", + "example": "2023-12-19T20:09:12.583Z" + }, + "active": { + "type": "integer", + "minimum": 0, + "example": 10 + }, + "ignored": { + "type": "integer", + "minimum": 0, + "example": 241 + }, + "remediated": { + "type": "integer", + "minimum": 0, + "example": 51 + } + } + }, + "totalProjects": { + "type": "integer", + "minimum": 0, + "example": 9 + }, + "licensing": { + "type": "object", + "properties": { + "type": { + "type": "object", + "properties": { + "policy_conflict": { + "type": "integer", + "minimum": 0, + "example": 59 + }, + "policy_flag": { + "type": "integer", + "minimum": 0, + "example": 210 + }, + "unlicensed_dependency": { + "type": "integer", + "minimum": 0, + "example": 2 + } + } + }, + "status": { + "type": "object", + "properties": { + "active": { + "type": "integer", + "minimum": 0, + "example": 271 + }, + "ignored": { + "type": "integer", + "minimum": 0, + "example": 4 + }, + "remediated": { + "type": "integer", + "minimum": 0, + "example": 0 + } + } + } + } + }, + "vulnerability": { + "type": "object", + "properties": { + "type": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "example": 11 + }, + "high": { + "type": "integer", + "minimum": 0, + "example": 52 + }, + "medium": { + "type": "integer", + "minimum": 0, + "example": 4 + }, + "low": { + "type": "integer", + "minimum": 0, + "example": 99 + }, + "unknown": { + "type": "integer", + "minimum": 0, + "example": 42 + } + } + }, + "status": { + "type": "object", + "properties": { + "active": { + "type": "integer", + "minimum": 0, + "example": 208 + }, + "ignored": { + "type": "integer", + "minimum": 0, + "example": 2 + }, + "remediated": { + "type": "integer", + "minimum": 0, + "example": 5 + } + } + } + } + }, + "quality": { + "type": "object", + "properties": { + "type": { + "type": "object", + "properties": { + "outdated_dependency": { + "type": "integer", + "minimum": 0, + "example": 40 + }, + "blacklisted_dependency": { + "type": "integer", + "minimum": 0, + "example": 19 + }, + "risk_abandonware": { + "type": "integer", + "minimum": 0, + "example": 16 + }, + "risk_empty-package": { + "type": "integer", + "minimum": 0, + "example": 1 + }, + "risk_native-code": { + "type": "integer", + "minimum": 0, + "example": 6 + } + } + }, + "status": { + "type": "object", + "properties": { + "active": { + "type": "integer", + "minimum": 0, + "example": 82 + }, + "ignored": { + "type": "integer", + "minimum": 0, + "example": 25 + }, + "remediated": { + "type": "integer", + "minimum": 0, + "example": 6 + } + } + } + } + } + } + }, + "examples": { + "Success": { + "value": { + "counts": { + "date": "2023-12-19T20:09:12.583Z", + "active": 10, + "ignored": 241, + "remediated": 51 + }, + "totalProjects": 9, + "licensing": { + "type": { + "policy_conflict": 59, + "policy_flag": 210, + "unlicensed_dependency": 2 + }, + "status": { + "active": 271, + "ignored": 4, + "remediated": 0 + } + }, + "vulnerability": { + "type": { + "critical": 11, + "high": 52, + "medium": 4, + "low": 99, + "unknown": 42 + }, + "status": { + "active": 208, + "ignored": 2, + "remediated": 5 + } + }, + "quality": { + "type": { + "outdated_dependency": 40, + "blacklisted_dependency": 19, + "risk_abandonware": 16, + "risk_empty-package": 1, + "risk_native-code": 6 + }, + "status": { + "active": 82, + "ignored": 25, + "remediated": 6 + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "User Not Associated With Org": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "User is not associated with an organization.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Permissions": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "User does not have permission to see every project and every issue category.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/issue_counts/export": { + "post": { + "operationId": "exportIssueOverviewCsv", + "description": "Exports the issues from the current set of Issue Overview data.", + "tags": [ + "Issue Overview" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "start", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to 30 days before the end date.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "end", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to the current date and time.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "The project labels to filter Issue Overview data to.", + "schema": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + } + }, + { + "name": "category", + "description": "The issue category to filter Issue Overview data to. If no category is chosen, it will fetch data for all issue categories.", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + { + "name": "projectId", + "description": "The specific project ID to filter Issue Overview data to.", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + } + ], + "responses": { + "200": { + "description": "Okay", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "jobToken": { + "type": "string", + "description": "The job token used by the frontend when polling for updates.", + "example": "f49923d3-c522-4c6b-ab80-f38527d28a46" + }, + "task": { + "type": "string", + "description": "The name of the background task.", + "example": "ExportIssueSnapshots" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "User Not Associated With Org": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "User is not associated with an organization.", + "name": "BadRequestError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Permissions": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "User does not have permission to see every project and every issue category.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/cli/organization": { + "get": { + "operationId": "getOrganizationCLI", + "description": "Retrieves organizations capability and preferences for CLI. This is used by CLI to infer default preference and capability of an organization.\nFor example, 'supportsIssueDiffs' of True indicates to the CLI, that this organization, and this endpoint can support issue diffing.\n", + "tags": [ + "CLI" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Organizations capability and preferences for CLI", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "organizationId": { + "type": "integer", + "description": "Unique organization identifier" + }, + "usesSAML": { + "type": "boolean", + "description": "True if organization uses SAML, otherwise False." + }, + "supportsCliLicenseScanning": { + "type": "boolean", + "description": "True if organization supports CLI license scanning (native), otherwise False." + }, + "supportsAnalyzedRevisionsQuery": { + "type": "boolean", + "description": "True if organization supports analyzed revision query, otherwise False." + }, + "supportsDependenciesCachePolling": { + "type": "boolean", + "description": "True if organization supports dependencies cache polling, otherwise False." + }, + "supportsIssueDiffs": { + "type": "boolean", + "description": "True if organization supports issue diffing, otherwise False." + }, + "defaultVendoredDependencyScanType": { + "type": "string", + "enum": [ + "ArchiveUpload", + "CLILicenseScan" + ], + "description": "Default vendor scanning preferred by the organization." + }, + "supportsNativeContainerScans": { + "type": "boolean", + "description": "True if organization supports native container scanning, otherwise False." + }, + "requireFullFileUploads": { + "type": "boolean", + "description": "True if the organization wants CLI-side license scans to upload full file contents instead of just the match string" + }, + "supportsPathDependency": { + "type": "boolean", + "description": "True if the organization supports path dependencies. Otherwise False." + }, + "supportsFirstPartyScans": { + "type": "boolean", + "description": "True if the FOSSA instance supports first-party scans. Otherwise False." + }, + "defaultToFirstPartyScans": { + "type": "boolean", + "description": "True if the organization defaults to first-party scans. Otherwise False." + }, + "customLicenseScanConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + "description": "Configuration for custom license scans" + } + } + }, + "examples": { + "organizationPreferences": { + "value": { + "organizationId": 123, + "usesSAML": true, + "supportsCliLicenseScanning": true, + "supportsAnalyzedRevisionsQuery": true, + "supportsDependenciesCachePolling": true, + "supportsIssueDiffs": true, + "defaultVendoredDependencyScanType": "CLILicenseScan", + "supportsNativeContainerScans": true, + "requireFullFileUploads": true, + "supportsPathDependency": true, + "supportsFirstPartyScans": true, + "defaultToFirstPartyScans": false, + "customLicenseScanConfigs": [ + { + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/custom-risk-scores/{issueId}": { + "post": { + "operationId": "createCustomRiskScore", + "summary": "Create a custom risk score", + "description": "Creates a custom risk score for a vulnerability issue within a specific scope (project or release group).", + "tags": [ + "Custom Risk Scores" + ], + "parameters": [ + { + "name": "issueId", + "description": "ID of the vulnerability issue", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "scope[type]", + "description": "Scope type for the custom risk score", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "project", + "release_group" + ] + } + }, + { + "name": "scope[id]", + "description": "Project locator or release group ID", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "score" + ], + "properties": { + "score": { + "type": "integer", + "description": "The custom risk score (0-100 scale)", + "minimum": 0, + "maximum": 100, + "example": 75 + }, + "reason": { + "type": "string", + "description": "The reason for the custom risk score", + "maxLength": 500, + "example": "Adjusted based on internal risk assessment" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "201": { + "description": "The created custom risk score", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "issueId", + "score", + "scope", + "scopeId" + ], + "properties": { + "issueId": { + "type": "integer", + "description": "The ID of the issue", + "example": 12345 + }, + "score": { + "type": "integer", + "description": "The custom risk score (0-100 scale)", + "minimum": 0, + "maximum": 100, + "example": 75 + }, + "scope": { + "type": "string", + "description": "The scope type of the custom risk score", + "enum": [ + "project", + "release_group" + ], + "example": "project" + }, + "reason": { + "type": "string", + "nullable": true, + "description": "The reason for the custom risk score", + "maxLength": 500, + "example": "Adjusted based on internal risk assessment" + }, + "scopeId": { + "type": "string", + "description": "The project locator or release group ID", + "example": "custom+1/my-project" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Issue Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Issue not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "409": { + "description": "Custom risk score already exists for this issue in the specified scope", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "updateCustomRiskScore", + "summary": "Update a custom risk score", + "description": "Updates an existing custom risk score for a vulnerability issue within a specific scope (project or release group).", + "tags": [ + "Custom Risk Scores" + ], + "parameters": [ + { + "name": "issueId", + "description": "ID of the vulnerability issue", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "scope[type]", + "description": "Scope type for the custom risk score", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "project", + "release_group" + ] + } + }, + { + "name": "scope[id]", + "description": "Project locator or release group ID", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "score" + ], + "properties": { + "score": { + "type": "integer", + "description": "The custom risk score (0-100 scale)", + "minimum": 0, + "maximum": 100, + "example": 75 + }, + "reason": { + "type": "string", + "description": "The reason for the custom risk score", + "maxLength": 500, + "example": "Adjusted based on internal risk assessment" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "The updated custom risk score", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "issueId", + "score", + "scope", + "scopeId" + ], + "properties": { + "issueId": { + "type": "integer", + "description": "The ID of the issue", + "example": 12345 + }, + "score": { + "type": "integer", + "description": "The custom risk score (0-100 scale)", + "minimum": 0, + "maximum": 100, + "example": 75 + }, + "scope": { + "type": "string", + "description": "The scope type of the custom risk score", + "enum": [ + "project", + "release_group" + ], + "example": "project" + }, + "reason": { + "type": "string", + "nullable": true, + "description": "The reason for the custom risk score", + "maxLength": 500, + "example": "Adjusted based on internal risk assessment" + }, + "scopeId": { + "type": "string", + "description": "The project locator or release group ID", + "example": "custom+1/my-project" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Issue Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Issue not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteCustomRiskScore", + "summary": "Delete a custom risk score", + "description": "Deletes an existing custom risk score for a vulnerability issue within a specific scope (project or release group).", + "tags": [ + "Custom Risk Scores" + ], + "parameters": [ + { + "name": "issueId", + "description": "ID of the vulnerability issue", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "scope[type]", + "description": "Scope type for the custom risk score", + "required": true, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "project", + "release_group" + ] + } + }, + { + "name": "scope[id]", + "description": "Project locator or release group ID", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "204": { + "description": "Custom risk score successfully deleted" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Issue Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Issue not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/labels": { + "get": { + "operationId": "getOrganizationLabels", + "description": "Retrieves the Labels associated with the Organization.", + "tags": [ + "Organization Labels" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of this label" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that this Label is associated with" + }, + "label": { + "type": "string", + "description": "Text that this Label represents" + }, + "projects": { + "type": "array", + "items": { + "type": "string", + "description": "FOSSA's identifier for a unique component" + } + } + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createOrganizationLabel", + "description": "Creates a new Label associated with the Organization. Restricted to premium users.", + "tags": [ + "Organization Labels" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "Text that this Label represents" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of this label" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that this Label is associated with" + }, + "label": { + "type": "string", + "description": "Text that this Label represents" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/organizations/labels/{id}": { + "get": { + "operationId": "getOrganizationLabel", + "description": "Retrieves a specific Label by its ID.", + "tags": [ + "Organization Labels" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of this label" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that this Label is associated with" + }, + "label": { + "type": "string", + "description": "Text that this Label represents" + }, + "projects": { + "type": "array", + "items": { + "type": "string", + "description": "FOSSA's identifier for a unique component" + } + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOrganizationLabel", + "description": "Delete a specific Label by its ID. Restricted to premium users.", + "tags": [ + "Organization Labels" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "No content" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/limits/{resource}": { + "get": { + "operationId": "getOrganizationLimits", + "description": "Fetch the organization's limit for subscription limited resource and its current usage.", + "tags": [ + "Organization Limits" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "number" + }, + "description": "The organization ID." + }, + { + "in": "path", + "name": "resource", + "required": true, + "schema": { + "type": "string", + "enum": [ + "contributors", + "release-groups" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "usage": { + "type": "integer", + "minimum": 0, + "description": "The current usage of the resource." + }, + "max": { + "type": "integer", + "minimum": 0, + "description": "The contractual limit of the resource." + }, + "unlimited": { + "type": "boolean", + "description": "Whether or not the organization has an unlimited cap on the resource." + } + }, + "description": "An object that provides the current usage of a resource, the contractual limit of the resource, and whether or not the organization has an unlimited cap on the resource.\n" + }, + "examples": { + "Contributor limit for an organization": { + "value": { + "usage": 10, + "max": 100, + "unlimited": false + } + } + } + } + } + }, + "400": { + "description": "Bad Request error. Sent when an enterprise organization is missing an contract data.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Organization contract data is missing": { + "value": { + "uuid": "12345678-1234-1234-1234-123456789012", + "code": 400, + "message": "Organization contract not found.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Requesting for another org": { + "value": { + "uuid": "12345678-1234-1234-1234-123456789012", + "code": 403, + "message": "User does not have access for this Organization resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/labels": { + "get": { + "operationId": "getProjectLabels", + "description": "Retrieves the Labels associated with a specific Project.", + "tags": [ + "Project Labels" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of this label" + }, + "label": { + "type": "string", + "description": "Text that this Label represents" + } + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/last-published": { + "get": { + "operationId": "getProjectLastPublished", + "description": "Retrieves the timestamp of the last time the project received an update.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string", + "description": "The ISO timestamp of the last time an update was published for the project." + }, + "example": "2023-09-22T10:30:00Z" + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/projects/{locator}": { + "put": { + "operationId": "updateProject", + "summary": "Update a project's settings and configuration.", + "description": "Update a project's settings and configuration. This endpoint allows updating a wide variety of project properties\nincluding metadata, policy assignments, scanning settings, integration configurations, and more.\n\n## Permission Requirements\n\nMost fields require Edit permission on the project. The following fields require special permissions:\n- `public`: Requires MakePublic permission\n- `policyId`, `securityPolicyId`, `qualityPolicyId`, `sbomPolicyId`, `sbomAnalysisEnabled`: Require SetPolicy permission for the respective policy type\n\n## Special Behaviors\n\n### Branch Management\n- `tracking_branches` and `hidden_branches` are mutually exclusive. Adding a branch to one will automatically remove it from the other.\n- Only branches can be added to these arrays; tags are filtered out automatically.\n\n### Policy Changes\n- When policies or scanning settings change, the project will be automatically rescanned if the last analyzed revision is in a steady state.\n\n### Feature Flags\n- `securityIssueScanningEnabled` and `qualityIssueScanningEnabled` can only be modified if the organization has the respective features enabled.\n\n### Issue Tracker Fields\n- When updating `issueTrackerCustomFields`, boolean values in the `isRequired` field may be stringified and will be automatically converted.\n- Custom field configurations are validated against Jira field requirements.\n\n### Notifications\n- Empty notification objects are automatically filtered out.\n- Notification changes are processed asynchronously.\n", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "The URL-encoded locator of the project (e.g., \"git+github.com/owner/repo\")", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "example": "git%2Bgithub.com%2Ffossas%2Ffossa-cli" + } + ], + "requestBody": { + "description": "Project fields to update. All fields are optional. Only the fields provided will be updated; omitted fields remain unchanged.\nNote: The endpoint filters out any fields not in the allowed list automatically.\n", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Display name of the project", + "minLength": 1, + "example": "My FOSSA Project" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Detailed description of the project", + "example": "A sample project for demonstrating FOSSA features" + }, + "url": { + "type": "string", + "nullable": true, + "description": "Project homepage URL", + "example": "https://github.com/fossas/fossa-cli" + }, + "notes": { + "type": "string", + "nullable": true, + "description": "Internal notes about the project", + "example": "Critical production project - handle with care" + }, + "public": { + "type": "boolean", + "nullable": true, + "description": "Whether the project is publicly accessible. Requires MakePublic permission.\nPublic projects can be viewed by anyone with the link.\n", + "example": false + }, + "scm_url": { + "type": "string", + "nullable": true, + "description": "Source control management URL for the project repository", + "example": "https://github.com/fossas/fossa-cli.git" + }, + "manual_scm_url": { + "type": "boolean", + "description": "Whether the SCM URL was manually provided by the user", + "example": false + }, + "vcs_host": { + "type": "string", + "nullable": true, + "description": "VCS hosting provider", + "enum": [ + "github", + "gitlab", + "bitbucket", + "azure", + "other" + ], + "example": "github" + }, + "default_branch": { + "type": "string", + "description": "The default branch to analyze for this project", + "example": "main" + }, + "tracking_branches": { + "type": "array", + "nullable": true, + "description": "Branches to actively track and analyze. Tags are automatically filtered out.\nBranches in this list are automatically removed from `hidden_branches`.\n", + "items": { + "type": "string" + }, + "example": [ + "main", + "develop", + "staging" + ] + }, + "hidden_branches": { + "type": "array", + "nullable": true, + "description": "Branches to hide from the UI. Tags are automatically filtered out.\nBranches in this list are automatically removed from `tracking_branches`.\n", + "items": { + "type": "string" + }, + "example": [ + "feature/*", + "hotfix/*" + ] + }, + "policyId": { + "type": "integer", + "nullable": true, + "description": "ID of the licensing policy to apply to this project. Requires SetPolicy permission for LICENSING policy type.", + "example": 123 + }, + "securityPolicyId": { + "type": "integer", + "nullable": true, + "description": "ID of the security policy to apply to this project. Requires SetPolicy permission for SECURITY policy type.", + "example": 456 + }, + "qualityPolicyId": { + "type": "integer", + "nullable": true, + "description": "ID of the quality policy to apply to this project. Requires SetPolicy permission for QUALITY policy type.", + "example": 789 + }, + "sbomPolicyId": { + "type": "integer", + "nullable": true, + "description": "ID of the SBOM policy to apply to this project. Requires SetPolicy permission for SBOM policy type.", + "example": 321 + }, + "policies_approve_multilicense": { + "type": "boolean", + "description": "Whether to automatically approve dependencies with multiple licenses if any license is approved", + "example": false + }, + "licensingIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable licensing issue scanning for this project", + "example": true + }, + "securityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable security vulnerability scanning for this project.\nCan only be modified if the organization has security features enabled.\n", + "example": true + }, + "qualityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable quality issue scanning for this project.\nCan only be modified if the organization has quality features enabled.\n", + "example": false + }, + "sbomAnalysisEnabled": { + "type": "boolean", + "description": "Enable or disable SBOM policy analysis for this project. Requires SetPolicy permission for SBOM policy type.", + "example": false + }, + "snippetLicensingIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet licensing issue scanning for this project", + "example": false + }, + "snippetSecurityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet security issue scanning for this project", + "example": false + }, + "licensingStatusCheckEnabled": { + "type": "boolean", + "description": "Enable or disable licensing issue CI/CD status checks", + "example": true + }, + "securityStatusCheckEnabled": { + "type": "boolean", + "description": "Enable or disable security issue CI/CD status checks", + "example": true + }, + "qualityStatusCheckEnabled": { + "type": "boolean", + "description": "Enable or disable quality issue CI/CD status checks", + "example": false + }, + "excludeBaseLayerIssuesLicensing": { + "type": "boolean", + "description": "Exclude licensing issues found in container base layers", + "example": false + }, + "excludeBaseLayerIssuesSecurity": { + "type": "boolean", + "description": "Exclude security issues found in container base layers", + "example": true + }, + "excludeBaseLayerIssuesQuality": { + "type": "boolean", + "description": "Exclude quality issues found in container base layers", + "example": false + }, + "integrationhook_timeout": { + "type": "integer", + "description": "Timeout in seconds for integration hooks (e.g., GitHub status checks)", + "minimum": 0, + "example": 600 + }, + "integrationhook_fail_state": { + "type": "string", + "description": "Status to report when a hook times out or fails", + "enum": [ + "ERROR", + "SUCCESS" + ], + "example": "ERROR" + }, + "issue_tracker_url": { + "type": "string", + "nullable": true, + "description": "URL of the external issue tracker (e.g., Jira, GitHub Issues)", + "example": "https://jira.example.com/projects/PROJ" + }, + "issue_tracker_type": { + "type": "string", + "nullable": true, + "description": "Type of issue tracker", + "enum": [ + "github", + "jira" + ], + "example": "jira" + }, + "issueTrackerLabels": { + "type": "array", + "nullable": true, + "description": "Labels to automatically apply to issues created in the tracker", + "items": { + "type": "string" + }, + "example": [ + "fossa", + "security" + ] + }, + "issueTrackerIssueTypes": { + "type": "array", + "nullable": true, + "description": "Jira issue types available for this project", + "items": { + "type": "string" + }, + "example": [ + "Bug", + "Task", + "Story" + ] + }, + "issueTrackerProjectIds": { + "type": "array", + "nullable": true, + "description": "Jira project IDs associated with this project", + "items": { + "type": "string" + }, + "example": [ + "PROJ-123", + "PROJ-456" + ] + }, + "issueTrackerCustomFields": { + "type": "object", + "nullable": true, + "description": "Custom Jira fields configuration. The object keys are Jira field IDs, and values contain field metadata.\nThe `isRequired` field accepts both boolean and stringified boolean values (\"true\"/\"false\").\n", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The Jira custom field ID" + }, + "displayName": { + "type": "string", + "description": "Display name for the field in FOSSA UI" + }, + "isRequired": { + "type": "boolean", + "description": "Whether this field is required when creating issues (accepts \"true\"/\"false\" strings which are converted to boolean)" + }, + "defaultValue": { + "type": "string", + "description": "Default value for the field" + } + } + }, + "example": { + "customfield_10001": { + "fieldId": "customfield_10001", + "displayName": "Epic Link", + "isRequired": true, + "defaultValue": "EPIC-123" + } + } + }, + "useGlobalTrackerSettings": { + "type": "boolean", + "nullable": true, + "description": "Whether to use organization-level issue tracker settings instead of project-specific settings", + "example": false + }, + "transitive_excludes": { + "type": "array", + "nullable": true, + "description": "List of dependency locators to exclude from analysis. Removing items from this array is logged as \"un-ignoring\" dependencies.\nFormat: \"fetcher+package$revision\" (e.g., \"npm+lodash$4.17.21\")\n", + "items": { + "type": "string" + }, + "example": [ + "npm+debug$2.6.9", + "maven+com.google.guava:guava$29.0-jre" + ] + }, + "reportCustomText": { + "type": "string", + "nullable": true, + "description": "Custom text to include in attribution reports for this project", + "example": "For questions about this project, contact legal@example.com" + }, + "bom_column_settings": { + "type": "array", + "nullable": true, + "description": "Columns to display in the Bill of Materials (BOM) report.\nAvailable options: All, Name, Version, Type, License, DirectLicense, DirectLicenseOrigin,\nDeepLicense, DeepLicenseOrigin, Description, Homepage, PrimaryLanguage, SourceLocation,\nReleasePublishDate, OriginId, Tags, ComponentComment, Reachability\n", + "items": { + "type": "string", + "enum": [ + "All", + "Name", + "Version", + "Type", + "License", + "DirectLicense", + "DirectLicenseOrigin", + "DeepLicense", + "DeepLicenseOrigin", + "Description", + "Homepage", + "PrimaryLanguage", + "SourceLocation", + "ReleasePublishDate", + "OriginId", + "Tags", + "ComponentComment", + "Reachability" + ] + }, + "example": [ + "Name", + "Version", + "License", + "Description" + ] + }, + "bom_public_id": { + "type": "string", + "nullable": true, + "description": "Public identifier for accessing the project's attribution report", + "example": "abc123def456" + }, + "labels": { + "type": "array", + "description": "Array of label IDs to associate with this project. This replaces all existing labels.\nLabels must exist in the organization before being assigned.\n", + "items": { + "type": "integer" + }, + "example": [ + 1, + 5, + 12 + ] + }, + "filters": { + "type": "object", + "nullable": true, + "description": "Issue filter IDs to apply for each issue category. This configures which saved filters are used\nwhen viewing issues for this project. Set to null or omit to clear filters.\n", + "properties": { + "licensing": { + "type": "integer", + "nullable": true, + "description": "Saved filter ID for licensing issues" + }, + "vulnerability": { + "type": "integer", + "nullable": true, + "description": "Saved filter ID for security/vulnerability issues" + }, + "quality": { + "type": "integer", + "nullable": true, + "description": "Saved filter ID for quality issues" + } + }, + "example": { + "licensing": 101, + "vulnerability": 102, + "quality": null + } + }, + "notifications": { + "type": "array", + "nullable": true, + "description": "Array of notification configurations for this project. Empty notification objects are automatically filtered out.\nChanges are processed asynchronously alongside the main update.\n", + "items": { + "type": "object", + "required": [ + "channel", + "service" + ], + "properties": { + "id": { + "type": "integer", + "description": "Notification ID (for updates to existing notifications)" + }, + "channel": { + "type": "string", + "enum": [ + "SCAN" + ], + "description": "The event channel that triggers this notification" + }, + "service": { + "type": "string", + "enum": [ + "EMAIL", + "SLACK", + "API_WEBHOOK" + ], + "description": "The service to use for sending notifications" + }, + "subscribed_users": { + "type": "array", + "nullable": true, + "description": "Array of user IDs to receive EMAIL notifications", + "items": { + "type": "integer" + } + } + } + }, + "example": [ + { + "channel": "SCAN", + "service": "EMAIL", + "subscribed_users": [ + 1, + 2, + 3 + ] + }, + { + "channel": "SCAN", + "service": "SLACK", + "subscribed_users": null + } + ] + } + } + }, + "examples": { + "updateBasicInfo": { + "summary": "Update basic project information", + "value": { + "title": "Updated Project Name", + "description": "New project description", + "notes": "Updated internal notes" + } + }, + "updatePoliciesAndScanning": { + "summary": "Update policies and enable scanning", + "value": { + "policyId": 123, + "securityPolicyId": 456, + "licensingIssueScanningEnabled": true, + "securityIssueScanningEnabled": true, + "licensingStatusCheckEnabled": true, + "securityStatusCheckEnabled": true + } + }, + "updateBranchTracking": { + "summary": "Configure branch tracking", + "value": { + "default_branch": "main", + "tracking_branches": [ + "main", + "develop", + "release/*" + ], + "hidden_branches": [ + "feature/*", + "bugfix/*" + ] + } + }, + "updateJiraIntegration": { + "summary": "Configure Jira integration", + "value": { + "issue_tracker_url": "https://jira.example.com/projects/PROJ", + "issue_tracker_type": "jira", + "issueTrackerLabels": [ + "fossa", + "compliance" + ], + "issueTrackerIssueTypes": [ + "Bug", + "Task" + ], + "issueTrackerProjectIds": [ + "PROJ" + ], + "issueTrackerCustomFields": { + "customfield_10001": { + "fieldId": "customfield_10001", + "displayName": "Epic Link", + "isRequired": true + } + } + } + }, + "updateNotifications": { + "summary": "Configure email and Slack notifications", + "value": { + "notifications": [ + { + "channel": "SCAN", + "service": "EMAIL", + "subscribed_users": [ + 1, + 2, + 3 + ] + }, + { + "channel": "SCAN", + "service": "SLACK" + } + ] + } + }, + "updateLabelsAndFilters": { + "summary": "Update labels and issue filters", + "value": { + "labels": [ + 1, + 5, + 12 + ], + "filters": { + "licensing": 101, + "vulnerability": 102, + "quality": 103 + } + } + }, + "enableSecurityStatusChecks": { + "summary": "Enable security status checks with a filter", + "description": "Enable security CI/CD status checks and apply a saved security filter.\nNote: The security filter is set via filters.vulnerability (not securityFilterId).\n", + "value": { + "securityStatusCheckEnabled": true, + "filters": { + "vulnerability": 250 + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Project updated successfully. Returns the complete project object with all updated fields\nplus computed metadata including recent revisions, notifications, references, contributor count,\nand dynamically populated fields.\n", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "The updated Project object. Contains all the fields that can be updated via this endpoint,\nplus additional computed/metadata fields like organizationId, createdAt, updatedAt,\ncontributorCount, head/latest/last_analyzed revisions, notifications, references, and filters.\n" + }, + "examples": { + "successResponse": { + "value": { + "locator": "git+github.com/fossas/fossa-cli", + "title": "FOSSA CLI", + "url": "https://github.com/fossas/fossa-cli", + "description": "Open source CLI for analyzing dependencies", + "public": false, + "default_branch": "main", + "tracking_branches": [ + "main", + "develop" + ], + "policyId": 123, + "securityPolicyId": 456, + "licensingIssueScanningEnabled": true, + "securityIssueScanningEnabled": true, + "licensingStatusCheckEnabled": true, + "securityStatusCheckEnabled": true, + "organizationId": 1, + "contributorCount": 42, + "createdAt": "2023-01-15T10:30:00Z", + "updatedAt": "2024-03-20T14:22:10Z", + "labels": [], + "filters": { + "licensing": 101, + "vulnerability": 102 + }, + "notifications": [ + { + "id": 1, + "channel": "SCAN", + "service": "EMAIL", + "subscribed_users": [ + 1, + 2 + ] + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Invalid input or validation error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "malformedPath": { + "summary": "Malformed path parameter", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Malformed path, expected a locator", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "emptyTitle": { + "summary": "Empty project title", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Project title cannot be empty.", + "name": "MalformedPayloadError", + "httpStatusCode": 400 + } + }, + "invalidCustomFields": { + "summary": "Invalid Jira custom fields", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Invalid custom field configuration", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden - Insufficient permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "noEditPermission": { + "summary": "No edit permission", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "Only project maintainers can update project settings.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "wrongOrganization": { + "summary": "Project belongs to different organization", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "You do not have permission to update this project.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Not Found - Project does not exist", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "projectNotFound": { + "summary": "Project not found", + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2004, + "message": "Project not found for git+github.com/example/repo", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/revisions": { + "get": { + "operationId": "getProjectRevisions", + "description": "List Revisions for the branches and tags of a given project.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the project - matched by substring", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "offset", + "description": "the number of revisions to skip for pagination (used with \"count\" query parameter)", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "count", + "description": "the number of revisions to return (maximum of 1000)", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "resolved", + "description": "If true, we will only return Revisions that have been successfully analyzed by FOSSA (resolved)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "refs[]", + "description": "the list of branches or tags being requested", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "refs_type", + "description": "Specify whether the list should be tags OR branches", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "branch", + "tag" + ] + } + }, + { + "name": "source", + "description": "Filter the revisions by source", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "github", + "gitlab", + "bitbucket", + "azure", + "cli", + "archive", + "container", + "sbom" + ] + } + } + ], + "responses": { + "200": { + "description": "A map of branches and tags of the Project to a sorted list of Revisions belonging to the corresponding tag/branch", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "branch": { + "type": "object", + "description": "map of branches to their Revisions", + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Normalized representation of the Locator", + "properties": { + "fetcher": { + "type": "string", + "description": "the external package manager or internal representation of one" + }, + "package": { + "type": "string", + "description": "the package name" + }, + "revision": { + "type": "string", + "description": "the version/revision of the package" + } + } + }, + "locator": { + "type": "string", + "description": "Text ID that uniquely identifies a project" + }, + "resolved": { + "type": "boolean", + "description": "Has the Revision been fully analyzed by FOSSA" + }, + "projectId": { + "type": "string", + "description": "The Project locator that the Revision belongs to" + }, + "source_type": { + "type": [ + "string", + "null" + ], + "description": "FOSSA internal representation of the source language for the given repository/project" + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message during analysis (if any)" + }, + "message": { + "type": [ + "string", + "null" + ], + "description": "Message of the revision or commit" + }, + "revision_timestamp": { + "type": [ + "string", + "null" + ], + "description": "timestamp of when the Revision was published" + }, + "latestRevisionScanId": { + "type": [ + "number", + "null" + ], + "description": "The Revision Scan ID of the latest policy scan" + }, + "latestHubbleAnalysisId": { + "type": [ + "number", + "null" + ], + "description": "The Hubble Analysis ID of the latest analysis" + }, + "createdAt": { + "type": "string", + "description": "when the Revision was added to the FOSSA Database" + }, + "updatedAt": { + "type": "string", + "description": "when the Revision was last updated in the FOSSA Database" + }, + "author": { + "type": [ + "string", + "null" + ], + "description": "The author of the Revision" + }, + "link": { + "type": [ + "string", + "null" + ], + "description": "The link associated with the Revision" + }, + "url": { + "type": [ + "string", + "null" + ], + "description": "The url associated with the Revision" + } + } + } + } + }, + "tag": { + "type": "object", + "description": "map of tags to their Revisions", + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Normalized representation of the Locator", + "properties": { + "fetcher": { + "type": "string", + "description": "the external package manager or internal representation of one" + }, + "package": { + "type": "string", + "description": "the package name" + }, + "revision": { + "type": "string", + "description": "the version/revision of the package" + } + } + }, + "locator": { + "type": "string", + "description": "Text ID that uniquely identifies a project" + }, + "resolved": { + "type": "boolean", + "description": "Has the Revision been fully analyzed by FOSSA" + }, + "projectId": { + "type": "string", + "description": "The Project locator that the Revision belongs to" + }, + "source_type": { + "type": [ + "string", + "null" + ], + "description": "FOSSA internal representation of the source language for the given repository/project" + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message during analysis (if any)" + }, + "message": { + "type": [ + "string", + "null" + ], + "description": "Message of the revision or commit" + }, + "revision_timestamp": { + "type": [ + "string", + "null" + ], + "description": "timestamp of when the Revision was published" + }, + "latestRevisionScanId": { + "type": [ + "number", + "null" + ], + "description": "The Revision Scan ID of the latest policy scan" + }, + "latestHubbleAnalysisId": { + "type": [ + "number", + "null" + ], + "description": "The Hubble Analysis ID of the latest analysis" + }, + "createdAt": { + "type": "string", + "description": "when the Revision was added to the FOSSA Database" + }, + "updatedAt": { + "type": "string", + "description": "when the Revision was last updated in the FOSSA Database" + }, + "author": { + "type": [ + "string", + "null" + ], + "description": "The author of the Revision" + }, + "link": { + "type": [ + "string", + "null" + ], + "description": "The link associated with the Revision" + }, + "url": { + "type": [ + "string", + "null" + ], + "description": "The url associated with the Revision" + } + } + } + } + } + } + }, + "examples": { + "Branches": { + "value": { + "branch": { + "main": [ + { + "locator": "git+github.com/test1/test2$1.2.3", + "loc": { + "fetcher": "git", + "package": "github.com/test1/test2", + "revision": "1.2.3" + }, + "resolved": true, + "projectId": "git+github.com/test1/test2", + "source_type": "rubygem", + "error": "", + "message": "commit message 1", + "revision_timestamp": "2018-03-06T23:42:29.000Z", + "latestRevisionScanId": 1, + "latestHubbleAnalysisId": 1, + "createdAt": "2022-01-28T03:22:28.183Z", + "updatedAt": "2023-12-05T00:19:44.400Z" + }, + { + "locator": "git+github.com/test1/test2$4.5.6", + "loc": { + "fetcher": "git", + "package": "github.com/test1/test2", + "revision": "4.5.6" + }, + "resolved": true, + "projectId": "git+github.com/test1/test2", + "source_type": "rubygem", + "error": "", + "message": "commit message 2", + "revision_timestamp": "2019-03-06T23:42:29.000Z", + "latestRevisionScanId": 2, + "latestHubbleAnalysisId": 2, + "createdAt": "2022-01-28T03:22:28.183Z", + "updatedAt": "2023-12-05T00:19:44.400Z" + } + ], + "develop": [ + { + "locator": "git+github.com/test1/test2$7.8.9", + "loc": { + "fetcher": "git", + "package": "github.com/test1/test2", + "revision": "7.8.9" + }, + "resolved": true, + "projectId": "git+github.com/test1/test2", + "source_type": "rubygem", + "error": "", + "message": "commit message 3", + "revision_timestamp": "2022-03-06T23:42:29.000Z", + "latestRevisionScanId": 3, + "latestHubbleAnalysisId": 3, + "createdAt": "2022-01-28T03:22:28.183Z", + "updatedAt": "2023-12-05T00:19:44.400Z" + } + ] + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Non array refs query parameter": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "refs must be an array", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "No Revision data found for the provided Project: X and request parameters", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/generate_attribution_slug": { + "put": { + "operationId": "generateProjectGenerateAttributionSlug", + "description": "Generate (or regenerate) a slug used in the URL for the live attribution report for this project", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "string" + }, + "examples": { + "Success": { + "value": "00000-1111-2222-333333333333" + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad request": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Bad request.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Invalid Permissions": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "User does not have permission to edit this project.", + "name": "ForbiddenError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Project Not Found": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2004, + "message": "Project could not be found or you do not have access to it.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjectGenerateAttributionSlug", + "description": "Delete a slug used in the URL for the live attribution report for this project", + "tags": [ + "Projects", + "Issues" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No content" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad request": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Bad request.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthenticated Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Permissions": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2005, + "message": "User does not have permission to edit this project.", + "name": "ForbiddenError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Project Not Found": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2004, + "message": "Project could not be found or you do not have access to it.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/export-issues": { + "get": { + "operationId": "getProjectExportIssues", + "description": "This endpoint returns a list of all issues for a project. The issues are exported in a JSON (or CSV) format.\n", + "tags": [ + "Projects", + "Issues" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the project", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "format", + "description": "report format to return (JSON or CSV). If not provided, JSON will be returned.", + "required": false, + "in": "query", + "schema": { + "type": { + "enum": [ + "json", + "csv" + ] + } + } + }, + { + "name": "revisionId", + "description": "The revisionId of the project to get issues for. If not provided, the latest revision will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "description": "The status of the issues to return. If not provided, all active issues will be returned.", + "required": false, + "in": "query", + "schema": { + "type": { + "enum": [ + "active", + "ignored" + ] + } + } + }, + { + "name": "ref", + "description": "the branch or tag to get issues for. If not provided, the default branch will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "ref_type", + "description": "Specify whether the ref is a branch or tag.", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "branch", + "tag" + ] + } + } + ], + "responses": { + "200": { + "description": "A report of all issues for the project. Either in JSON or CSV format.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Package License Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "Flagged by Policy": { + "description": "The policy that triggered the issue.\n", + "type": "string" + }, + "Issue Type": { + "description": "The type of issue.\n", + "type": "string" + }, + "License": { + "description": "The license that triggered the issue.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "Details": { + "description": "A description of the policy rule that triggered this issue (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + } + } + } + }, + "Vulnerability Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "description": "The plaintext name of the CWE that affects the dependency.\n", + "type": "string" + }, + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "CVE": { + "description": "The CVE that affects the dependency.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "CVSS": { + "description": "The CVSS Vector of the vulnerability.\n", + "type": "string" + }, + "CVSS Score": { + "description": "The CVSS Score of the vulnerability.\n", + "type": "string" + }, + "CVSS Severity": { + "description": "The CVSS Severity of the vulnerability.\n", + "type": "string" + }, + "Details": { + "description": "A description of the Vulnerability that triggered this issue (if available).\n", + "type": "string" + }, + "Remediation Advice": { + "description": "The version of the dependency that fixes all vulnerabilities on this dependency (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + }, + "Reference": { + "description": "Associated link to information on the vulnerability.\n", + "type": "string" + }, + "CWE": { + "description": "A CWE that affects the dependency.\n", + "type": "string" + } + } + } + }, + "Quality Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "Type": { + "description": "The type of issue.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "Details": { + "description": "A description of the policy rule that triggered this issue (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + } + } + } + } + } + }, + "examples": { + "JSON": { + "value": { + "Package License Issues": [ + { + "Dependency": "commonjs-findpkgs", + "Revision": "0.0.7", + "Flagged by Policy": "", + "Issue Type": "unlicensed dependency", + "License": "", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "", + "Dependency Depths": "1" + }, + { + "Dependency": "ansi-wl-pprint", + "Revision": "0.6.9", + "Flagged by Policy": "Standard Bundle Distribution", + "Issue Type": "disallowed project", + "License": "BSD 2-Clause \"Simplified\" License", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Permissive license which is perfectly safe to use provided proper attribution is given and retained.", + "Dependency Depths": "2" + } + ], + "Vulnerability Issues": [ + { + "Name": "Uncontrolled Resource Consumption", + "Dependency": "uglify-js", + "Revision": "2.4.24", + "CVE": "CVE-2015-8858", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "CVSS": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "CVSS Score": "7.5", + "CVSS Severity": "High", + "Details": "The uglify-js package before 2.6.0 for Node.js allows attackers to cause a denial of service (CPU consumption) via crafted input in a parse call aka a \"regular expression denial of service (ReDoS).\"", + "Remediation Advice": "2.6.0", + "Dependency Depths": "2", + "Reference": "https://github.com/advisories/GHSA-c9f4-xj24-8jqx", + "CWE": "CWE-399" + }, + { + "Name": "Uncontrolled Resource Consumption", + "Dependency": "uglify-js", + "Revision": "2.4.25", + "CVE": "CVE-2015-8869", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "CVSS": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "CVSS Score": "7.5", + "CVSS Severity": "High", + "Details": "The uglify-js package before 2.6.0 for Node.js allows attackers to cause a denial of service (CPU consumption) via crafted input in a parse call aka a \"regular expression denial of service (ReDoS).\"", + "Remediation Advice": "2.6.0", + "Dependency Depths": "2", + "Reference": "https://github.com/advisories/GHSA-c9f4-xj24-8jqx", + "CWE": "CWE-399" + } + ], + "Quality Issues": [ + { + "Dependency": "eslint", + "Revision": "7.32.0", + "Issue Type": "outdated dependency", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Major difference of 3 or more", + "Dependency Depths": "2" + }, + { + "Dependency": "eslint", + "Revision": "7.32.1", + "Issue Type": "outdated dependency", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Major difference of 3 or more", + "Dependency Depths": "2" + } + ] + } + } + } + }, + "text/csv": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Could not find project abcd", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "428": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid revisionId provided": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 1025, + "message": "Invalid revision specified", + "name": "NotFoundError", + "httpStatusCode": 428 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/export-issues/json": { + "get": { + "operationId": "getProjectJSONExportIssues", + "description": "This endpoint returns a list of all issues for a project. The issues are exported in a JSON format.\n", + "tags": [ + "Projects", + "Issues" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the project", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "revisionId", + "description": "The revisionId of the project to get issues for. If not provided, the latest revision will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "description": "The status of the issues to return. If not provided, all active issues will be returned.", + "required": false, + "in": "query", + "schema": { + "type": { + "enum": [ + "active", + "ignored" + ] + } + } + }, + { + "name": "ref", + "description": "the branch or tag to get issues for. If not provided, the default branch will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "ref_type", + "description": "Specify whether the ref is a branch or tag.", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "branch", + "tag" + ] + } + } + ], + "responses": { + "200": { + "description": "A report of all issues for the project.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Package License Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "Flagged by Policy": { + "description": "The policy that triggered the issue.\n", + "type": "string" + }, + "Issue Type": { + "description": "The type of issue.\n", + "type": "string" + }, + "License": { + "description": "The license that triggered the issue.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "Details": { + "description": "A description of the policy rule that triggered this issue (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + } + } + } + }, + "Vulnerability Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "description": "The plaintext name of the CWE that affects the dependency.\n", + "type": "string" + }, + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "CVE": { + "description": "The CVE that affects the dependency.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "CVSS": { + "description": "The CVSS Vector of the vulnerability.\n", + "type": "string" + }, + "CVSS Score": { + "description": "The CVSS Score of the vulnerability.\n", + "type": "string" + }, + "CVSS Severity": { + "description": "The CVSS Severity of the vulnerability.\n", + "type": "string" + }, + "Details": { + "description": "A description of the Vulnerability that triggered this issue (if available).\n", + "type": "string" + }, + "Remediation Advice": { + "description": "The version of the dependency that fixes all vulnerabilities on this dependency (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + }, + "References": { + "description": "Associated link's to information on the vulnerability.\n", + "type": "array", + "items": { + "type": "string" + } + }, + "CWES": { + "description": "List of CWE's that affects the dependency.\n", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "Quality Issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Dependency": { + "description": "The dependency that the issue is associated with.\n", + "type": "string" + }, + "Revision": { + "description": "The revision of the dependency that the issue is associated with.\n", + "type": "string" + }, + "Type": { + "description": "The type of issue.\n", + "type": "string" + }, + "FOSSA URL": { + "description": "A link to the project in the FOSSA UI.\n", + "type": "string" + }, + "Affected Project": { + "description": "The User Project that the issue is associated with.\n", + "type": "string" + }, + "Details": { + "description": "A description of the policy rule that triggered this issue (if available).\n", + "type": "string" + }, + "Dependency Depths": { + "description": "The depth(s) of the dependency in the dependency tree.\n", + "type": "string" + } + } + } + } + } + }, + "examples": { + "JSON": { + "value": { + "Package License Issues": [ + { + "Dependency": "commonjs-findpkgs", + "Revision": "0.0.7", + "Flagged by Policy": "", + "Issue Type": "unlicensed dependency", + "License": "", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "", + "Dependency Depths": "1" + }, + { + "Dependency": "ansi-wl-pprint", + "Revision": "0.6.9", + "Flagged by Policy": "Standard Bundle Distribution", + "Issue Type": "disallowed project", + "License": "BSD 2-Clause \"Simplified\" License", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Permissive license which is perfectly safe to use provided proper attribution is given and retained.", + "Dependency Depths": "2" + } + ], + "Vulnerability Issues": [ + { + "Name": "Uncontrolled Resource Consumption", + "Dependency": "uglify-js", + "Revision": "2.4.24", + "CVE": "CVE-2015-8858", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "CVSS": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "CVSS Score": "7.5", + "CVSS Severity": "High", + "Details": "The uglify-js package before 2.6.0 for Node.js allows attackers to cause a denial of service (CPU consumption) via crafted input in a parse call aka a \"regular expression denial of service (ReDoS).\"", + "Remediation Advice": "2.6.0", + "Dependency Depths": "2", + "References": [ + "https://github.com/advisories/GHSA-c9f4-xj24-8jqx", + "https://github.com/advisories/GHSA-c9f4-xj24-8jqz" + ], + "CWES": [ + "CWE-399", + "CWE-400" + ] + }, + { + "Name": "Uncontrolled Resource Consumption", + "Dependency": "uglify-js", + "Revision": "2.4.25", + "CVE": "CVE-2015-8869", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "CVSS": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "CVSS Score": "7.5", + "CVSS Severity": "High", + "Details": "The uglify-js package before 2.6.0 for Node.js allows attackers to cause a denial of service (CPU consumption) via crafted input in a parse call aka a \"regular expression denial of service (ReDoS).\"", + "Remediation Advice": "2.6.0", + "Dependency Depths": "2", + "References": [ + "https://github.com/advisories/GHSA-c9f4-xj24-8jqx", + "https://github.com/advisories/GHSA-c9f4-xj24-8jqz" + ], + "CWES": [ + "CWE-399", + "CWE-400" + ] + } + ], + "Quality Issues": [ + { + "Dependency": "eslint", + "Revision": "7.32.0", + "Issue Type": "outdated dependency", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Major difference of 3 or more", + "Dependency Depths": "2" + }, + { + "Dependency": "eslint", + "Revision": "7.32.1", + "Issue Type": "outdated dependency", + "Affected Project": "My project", + "FOSSA URL": "https://app.fossa.com/projects/myproject", + "Details": "Major difference of 3 or more", + "Dependency Depths": "2" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Could not find project abcd", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "428": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid revisionId provided": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 1025, + "message": "Invalid revision specified", + "name": "NotFoundError", + "httpStatusCode": 428 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/projects/{locator}/export-issues/csv": { + "get": { + "operationId": "getProjectCSVExportIssues", + "description": "This endpoint returns a CSV file of all issues for the project.\n", + "tags": [ + "Projects", + "Issues" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the project", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "revisionId", + "description": "The revisionId of the project to get issues for. If not provided, the latest revision will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "description": "The status of the issues to return. If not provided, all active issues will be returned.", + "required": false, + "in": "query", + "schema": { + "type": { + "enum": [ + "active", + "ignored" + ] + } + } + }, + { + "name": "ref", + "description": "the branch or tag to get issues for. If not provided, the default branch will be used.", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "ref_type", + "description": "Specify whether the ref is a branch or tag.", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "branch", + "tag" + ] + } + } + ], + "responses": { + "200": { + "description": "A report of all issues for the project.", + "content": { + "text/csv": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Could not find project abcd", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "428": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid revisionId provided": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 1025, + "message": "Invalid revision specified", + "name": "NotFoundError", + "httpStatusCode": 428 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/roles": { + "get": { + "operationId": "getAllRoles", + "description": "Get all roles for users in an organization", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "scope": { + "type": "string", + "description": "The role's scope", + "enum": [ + "organization", + "team" + ] + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "description": { + "type": "string", + "description": "The role's description" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The role's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The role's last update date" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "description": "The resource type" + }, + "action": { + "type": "string", + "description": "The action" + } + } + } + } + } + } + }, + "examples": { + "roles": { + "value": [ + { + "id": 1, + "organizationId": 1, + "isCustom": false, + "scope": "organization", + "name": "Org Admin", + "description": "Organization administrator, can do everything", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "permissions": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + } + ] + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createRole", + "description": "Create a new custom role", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "scope", + "name", + "description" + ], + "properties": { + "scope": { + "type": "string", + "enum": [ + "organization", + "team" + ], + "description": "Scope of the role", + "example": "organization" + }, + "name": { + "type": "string", + "description": "Name of the role", + "example": "Custom Admin Role" + }, + "description": { + "type": "string", + "description": "Description of the role", + "example": "Custom admin role with specific permissions" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "required": [ + "resourceType", + "action" + ], + "properties": { + "resourceType": { + "type": "string", + "description": "Resource type for the permission", + "example": "project_any" + }, + "action": { + "type": "string", + "description": "Action for the permission", + "example": "view" + } + } + }, + "description": "List of permissions for this role", + "example": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + } + ] + } + } + }, + "examples": { + "createOrganizationRole": { + "summary": "Create an organization-scoped role", + "value": { + "scope": "organization", + "name": "Custom Admin Role", + "description": "Custom admin role with specific permissions", + "permissions": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + } + ] + } + }, + "createTeamRole": { + "summary": "Create a team-scoped role", + "value": { + "scope": "team", + "name": "Team Lead Role", + "description": "Team lead with project management permissions", + "permissions": [ + { + "resourceType": "project", + "action": "view" + }, + { + "resourceType": "project", + "action": "edit" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Role created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "scope": { + "type": "string", + "description": "The role's scope", + "enum": [ + "organization", + "team" + ] + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "description": { + "type": "string", + "description": "The role's description" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The role's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The role's last update date" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "description": "The resource type" + }, + "action": { + "type": "string", + "description": "The action" + } + } + } + } + } + }, + "examples": { + "createdRole": { + "value": { + "id": 10, + "organizationId": 1, + "isCustom": true, + "scope": "organization", + "name": "Custom Admin Role", + "description": "Custom admin role with specific permissions", + "createdAt": "2023-01-01T00:00:00Z", + "updatedAt": "2023-01-01T00:00:00Z", + "permissions": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "EmptyRequestBody": { + "value": { + "message": "Empty request body.", + "code": 2003 + } + }, + "MissingField": { + "value": { + "message": "Missing role name in request.", + "code": 2003 + } + }, + "InvalidScope": { + "value": { + "message": "Invalid role scope \"invalid\" in request.", + "code": 2003 + } + }, + "RoleNameExists": { + "value": { + "message": "A role with the name \"Admin\" already exists in your organization.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to manage roles.", + "code": 2001 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/roles/{id}": { + "put": { + "operationId": "updateRole", + "description": "Update an existing custom role", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the role to update", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New name for the role", + "example": "Updated Admin Role" + }, + "description": { + "type": "string", + "description": "New description for the role", + "example": "Updated admin role with modified permissions" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "required": [ + "resourceType", + "action" + ], + "properties": { + "resourceType": { + "type": "string", + "description": "Resource type for the permission", + "example": "project_any" + }, + "action": { + "type": "string", + "description": "Action for the permission", + "example": "view" + } + } + }, + "description": "Updated list of permissions for this role", + "example": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + }, + { + "resourceType": "project_any", + "action": "delete" + } + ] + } + } + }, + "examples": { + "updateRole": { + "value": { + "name": "Updated Admin Role", + "description": "Updated admin role with modified permissions", + "permissions": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + }, + { + "resourceType": "project_any", + "action": "delete" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Role updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "scope": { + "type": "string", + "description": "The role's scope", + "enum": [ + "organization", + "team" + ] + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "description": { + "type": "string", + "description": "The role's description" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The role's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The role's last update date" + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "description": "The resource type" + }, + "action": { + "type": "string", + "description": "The action" + } + } + } + } + } + }, + "examples": { + "updatedRole": { + "value": { + "id": 10, + "organizationId": 1, + "isCustom": true, + "scope": "organization", + "name": "Updated Admin Role", + "description": "Updated admin role with modified permissions", + "createdAt": "2023-01-01T00:00:00Z", + "updatedAt": "2023-01-02T00:00:00Z", + "permissions": [ + { + "resourceType": "project_any", + "action": "view" + }, + { + "resourceType": "project_any", + "action": "edit" + }, + { + "resourceType": "project_any", + "action": "delete" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "EmptyRequestBody": { + "value": { + "message": "Empty request body.", + "code": 2003 + } + }, + "InvalidRoleId": { + "value": { + "message": "Invalid role ID parameter.", + "code": 2003 + } + }, + "BuiltinRoleEdit": { + "value": { + "message": "Built-in roles may not be edited.", + "code": 2003 + } + }, + "RoleNameExists": { + "value": { + "message": "A role with the name \"Admin\" already exists in your organization.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to manage roles.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "RoleNotFound": { + "value": { + "message": "Role not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteRole", + "description": "Delete a custom role. Built-in roles cannot be deleted. Roles assigned to users cannot be deleted.", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the role to delete", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Role deleted successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidRoleId": { + "value": { + "message": "Invalid role ID parameter.", + "code": 2003 + } + }, + "BuiltinRoleDelete": { + "value": { + "message": "Built-in roles may not be deleted.", + "code": 2003 + } + }, + "RoleInUse": { + "value": { + "message": "This role cannot be deleted because it is currently assigned to a user.", + "code": 2003 + } + }, + "RoleInUseMultiple": { + "value": { + "message": "This role cannot be deleted because it is currently assigned to 5 users.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to manage roles.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "RoleNotFound": { + "value": { + "message": "Role not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/roles/all-permissions": { + "get": { + "operationId": "getAllPermissions", + "description": "Get all available permissions that can be assigned to custom roles", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "description": "Resource type for the permission", + "example": "project_any" + }, + "action": { + "type": "string", + "description": "Action for the permission", + "example": "view" + }, + "scopes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Valid scopes for this permission", + "example": [ + "organization", + "team" + ] + }, + "group": { + "type": "string", + "description": "Permission group for UI organization", + "example": "Project" + }, + "description": { + "type": "string", + "description": "Human-readable description of the permission", + "example": "View any project in the organization" + } + } + } + }, + "examples": { + "permissions": { + "value": [ + { + "resourceType": "organization", + "action": "view", + "scopes": [ + "organization" + ], + "group": "Organization", + "description": "View organization settings" + }, + { + "resourceType": "project_any", + "action": "view", + "scopes": [ + "organization", + "team" + ], + "group": "Project", + "description": "View any project in the organization" + }, + { + "resourceType": "project_any", + "action": "edit", + "scopes": [ + "organization", + "team" + ], + "group": "Project", + "description": "Edit any project in the organization" + }, + { + "resourceType": "project", + "action": "view", + "scopes": [ + "team" + ], + "group": "Project", + "description": "View specific projects" + }, + { + "resourceType": "project", + "action": "edit", + "scopes": [ + "team" + ], + "group": "Project", + "description": "Edit specific projects" + }, + { + "resourceType": "role", + "action": "manage", + "scopes": [ + "organization" + ], + "group": "Role", + "description": "Manage roles and permissions" + }, + { + "resourceType": "user", + "action": "manage", + "scopes": [ + "organization" + ], + "group": "User", + "description": "Manage users in the organization" + }, + { + "resourceType": "team", + "action": "create", + "scopes": [ + "organization" + ], + "group": "Team", + "description": "Create new teams" + }, + { + "resourceType": "team", + "action": "edit", + "scopes": [ + "organization", + "team" + ], + "group": "Team", + "description": "Edit team settings" + }, + { + "resourceType": "policy", + "action": "manage", + "scopes": [ + "organization" + ], + "group": "Policy", + "description": "Manage organization policies" + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to manage roles.", + "code": 2001 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/roles/assignable": { + "get": { + "operationId": "getAssignableRoles", + "description": "Get roles that can be assigned by the current user. Returns only roles with equal or fewer permissions than the requesting user.", + "tags": [ + "Roles" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "assignableOrgRoles": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Array of role IDs that can be assigned for organization-scoped roles", + "example": [ + 1, + 2, + 10 + ] + }, + "assignableTeamRoles": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "integer" + } + }, + "description": "Object mapping team IDs to arrays of role IDs that can be assigned for those teams", + "example": { + "5": [ + 3, + 4, + 11 + ], + "6": [ + 3, + 4 + ] + } + } + } + }, + "examples": { + "assignableRoles": { + "value": { + "assignableOrgRoles": [ + 1, + 2, + 10 + ], + "assignableTeamRoles": { + "5": [ + 3, + 4, + 11 + ], + "6": [ + 3, + 4 + ] + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams": { + "get": { + "operationId": "getAllTeams", + "description": "This endpoint is deprecated. Please use the paginated /v2/teams/ endpoint instead.", + "deprecated": true, + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + }, + "defaultRoleId": { + "type": "integer", + "description": "The default role's unique identifier" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether the team auto-adds users" + }, + "uniqueIdentifier": { + "type": "string", + "description": "The team's unique identifier" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The team's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The team's last update date" + }, + "teamUsers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The user's unique identifier" + }, + "roleId": { + "type": "integer", + "description": "The role's unique identifier" + } + } + } + }, + "teamReleaseGroupsCount": { + "type": "integer", + "description": "The number of release groups associated with the team" + }, + "teamProjectsCount": { + "type": "integer", + "description": "The number of projects associated with the team" + } + } + } + }, + "examples": { + "teams": { + "value": [ + { + "id": 1, + "organizationId": 1, + "name": "Engineering", + "defaultRoleId": 1, + "autoAddUsers": false, + "description": "The engineering team", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "teamUsers": [ + { + "userId": 1, + "roleId": 2 + }, + { + "userId": 2, + "roleId": 2 + } + ], + "teamReleaseGroupsCount": 0, + "teamProjectsCount": 0 + }, + { + "id": 2, + "organizationId": 1, + "defaultRoleId": 2, + "autoAddUsers": false, + "name": "Security", + "description": "The security team", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "teamUsers": [ + { + "userId": 1, + "roleId": 2 + }, + { + "userId": 2, + "roleId": 2 + } + ], + "teamReleaseGroupsCount": 0, + "teamProjectsCount": 0 + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createTeam", + "description": "Create a new team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "defaultRoleId" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of the team", + "example": "Engineering" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for team members", + "example": 2 + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether to automatically add users to this team", + "example": false, + "default": false + }, + "uniqueIdentifier": { + "type": "string", + "description": "Unique identifier for the team", + "example": "eng-team-001", + "nullable": true + }, + "teamGroupIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "IDs of team groups to add this team to (requires team groups feature)", + "example": [ + 1, + 2 + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + }, + "defaultRoleId": { + "type": "integer", + "description": "The default role's unique identifier" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether the team auto-adds users" + }, + "uniqueIdentifier": { + "type": "string", + "description": "The team's unique identifier" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The team's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The team's last update date" + }, + "teamUsers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The user's unique identifier" + }, + "roleId": { + "type": "integer", + "description": "The role's unique identifier" + } + } + } + }, + "teamReleaseGroupsCount": { + "type": "integer", + "description": "The number of release groups associated with the team" + }, + "teamProjectsCount": { + "type": "integer", + "description": "The number of projects associated with the team" + } + } + }, + "examples": { + "createdTeam": { + "value": { + "id": 3, + "organizationId": 1, + "name": "Engineering", + "defaultRoleId": 2, + "autoAddUsers": false, + "uniqueIdentifier": "eng-team-001", + "createdAt": "2023-01-01T00:00:00Z", + "updatedAt": "2023-01-01T00:00:00Z", + "teamType": "team" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "EmptyRequestBody": { + "value": { + "message": "Empty request body.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to add teams to these team groups.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team group not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}": { + "put": { + "operationId": "updateTeam", + "description": "Update a team by ID", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team to update", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New name for the team", + "example": "Updated Engineering Team" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether to automatically add users to this team", + "example": true + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for team members", + "example": 3 + }, + "uniqueIdentifier": { + "type": "string", + "description": "Unique identifier for the team", + "example": "eng-team-updated", + "nullable": true + } + } + }, + "examples": { + "updateTeam": { + "value": { + "name": "Updated Engineering Team", + "autoAddUsers": true, + "defaultRoleId": 3, + "uniqueIdentifier": "eng-team-updated" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + }, + "defaultRoleId": { + "type": "integer", + "description": "The default role's unique identifier" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether the team auto-adds users" + }, + "uniqueIdentifier": { + "type": "string", + "description": "The team's unique identifier" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The team's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The team's last update date" + }, + "teamUsers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The user's unique identifier" + }, + "roleId": { + "type": "integer", + "description": "The role's unique identifier" + } + } + } + }, + "teamReleaseGroupsCount": { + "type": "integer", + "description": "The number of release groups associated with the team" + }, + "teamProjectsCount": { + "type": "integer", + "description": "The number of projects associated with the team" + } + } + }, + "examples": { + "updatedTeam": { + "value": { + "id": 1, + "organizationId": 1, + "name": "Updated Engineering Team", + "defaultRoleId": 3, + "autoAddUsers": true, + "uniqueIdentifier": "eng-team-updated", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2023-01-01T00:00:00Z", + "teamType": "team" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to update this team.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteTeam", + "description": "Delete a team by ID. This will remove the team from all team groups and delete all team associations.", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team to delete", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Team deleted successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to delete this team.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/teams": { + "get": { + "operationId": "getAllTeamsV2", + "description": "Get a paginated list of teams in your organization", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter teams by name (max 255)", + "schema": { + "type": "string", + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of teams", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + }, + "defaultRoleId": { + "type": "integer", + "description": "The default role's unique identifier" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether the team auto-adds users" + }, + "uniqueIdentifier": { + "type": "string", + "description": "The team's unique identifier" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The team's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The team's last update date" + }, + "teamType": { + "type": "string", + "enum": [ + "team", + "team_group" + ], + "description": "Whether it's a normal team or a Team Group." + }, + "teamMembersCount": { + "type": "integer", + "description": "The number of users associated with the team" + }, + "teamReleaseGroupsCount": { + "type": "integer", + "description": "The number of release groups associated with the team" + }, + "teamProjectsCount": { + "type": "integer", + "description": "The number of projects associated with the team" + } + } + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of teams" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "teams": { + "value": { + "results": [ + { + "id": 1, + "organizationId": 1, + "name": "Engineering", + "defaultRoleId": 1, + "autoAddUsers": false, + "uniqueIdentifier": "engineering", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "teamType": "team", + "teamMembersCount": 2, + "teamReleaseGroupsCount": 0, + "teamProjectsCount": 0 + }, + { + "id": 2, + "organizationId": 1, + "name": "Security", + "defaultRoleId": 2, + "autoAddUsers": false, + "uniqueIdentifier": "security", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "teamType": "team", + "teamMembersCount": 1, + "teamReleaseGroupsCount": 1, + "teamProjectsCount": 3 + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/teams/{id}": { + "get": { + "operationId": "getTeamByIdV2", + "description": "Get metadata about a team by ID", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + }, + "defaultRoleId": { + "type": "integer", + "description": "The default role's unique identifier" + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether the team auto-adds users" + }, + "uniqueIdentifier": { + "type": "string", + "description": "The team's unique identifier" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The team's creation date" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The team's last update date" + }, + "teamType": { + "type": "string", + "enum": [ + "team", + "team_group" + ], + "description": "Whether it's a normal team or a Team Group." + }, + "teamMembersCount": { + "type": "integer", + "description": "The number of members in the team" + }, + "teamReleaseGroupsCount": { + "type": "integer", + "description": "The number of release groups associated with the team" + }, + "teamProjectsCount": { + "type": "integer", + "description": "The number of projects associated with the team" + }, + "teamOIDCProvidersCount": { + "type": "integer", + "description": "The number of OIDC providers that can be accessed by members of this team. Includes both org-scoped providers and\nteam-scoped providers where the scopeId matches the team ID. This property is only returned if the user has\npermission to view OIDC providers.\n" + } + } + }, + "examples": { + "team": { + "value": { + "id": 1, + "organizationId": 1, + "name": "Engineering", + "defaultRoleId": 1, + "autoAddUsers": false, + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "teamType": "team", + "teamMembersCount": 3, + "teamReleaseGroupsCount": 0, + "teamProjectsCount": 0, + "teamOIDCProvidersCount": 0 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/members": { + "get": { + "operationId": "getTeamMembers", + "description": "Get a paginated list of members for a team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter team members by username or email", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of team members", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "ID of the user" + }, + "roleId": { + "type": "integer", + "description": "ID of the role assigned to the user in the team" + }, + "username": { + "type": "string", + "description": "Username of the user" + }, + "email": { + "type": "string", + "format": "email", + "description": "Email of the user" + }, + "isServiceAccount": { + "type": "boolean", + "description": "Whether the user is a service account" + } + }, + "required": [ + "userId", + "roleId", + "username", + "email" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of team members" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "teamMembers": { + "value": { + "results": [ + { + "userId": 1, + "roleId": 1, + "username": "admin_user", + "email": "admin@example.com" + }, + { + "userId": 2, + "roleId": 2, + "username": "team_member", + "email": "member@example.com" + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidPage": { + "value": { + "message": "Parse error: expected undefined | positive number at root.page but found \"not-a-number\"", + "code": 2003 + } + }, + "InvalidPageSize": { + "value": { + "message": "Parse error: expected undefined | positive number at root.pageSize but found \"not-a-number\"", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "You do not have permission to view this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/members/addable": { + "get": { + "operationId": "getAddableTeamUsers", + "description": "Get a paginated list of users that are not in the team and can be added.", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter users by username", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of users that can be added to the team", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "ID of the user" + }, + "username": { + "type": "string", + "description": "Username of the user" + }, + "email": { + "type": "string", + "format": "email", + "description": "Email of the user" + } + }, + "required": [ + "userId", + "username", + "email" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of users that can be added to the team" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "addableUsers": { + "value": { + "results": [ + { + "userId": 1, + "username": "admin_user", + "email": "admin@example.com" + }, + { + "userId": 2, + "username": "non_team_member", + "email": "non_team_member@example.com" + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidPage": { + "value": { + "message": "Parse error: expected undefined | positive number at root.page but found \"not-a-number\"", + "code": 2003 + } + }, + "InvalidPageSize": { + "value": { + "message": "Parse error: expected undefined | positive number at root.pageSize but found \"not-a-number\"", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "ForbiddenTeam": { + "value": { + "message": "You do not have permission to view this team.", + "code": 2005 + } + }, + "ForbiddenEdit": { + "value": { + "message": "You do not have permission to edit this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/users": { + "put": { + "operationId": "updateTeamUsers", + "description": "Update team users by adding, removing, or modifying user roles in the team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "action" + ], + "properties": { + "action": { + "type": "string", + "enum": [ + "add", + "remove", + "replace" + ], + "description": "Action to perform on team users", + "example": "add" + }, + "users": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "description": "ID of the user", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID for the user (required for add and update actions)", + "example": 2 + } + } + }, + "description": "List of users to add, remove, or replace" + } + } + }, + "examples": { + "addUsers": { + "summary": "Add users to team", + "value": { + "action": "add", + "users": [ + { + "id": 123, + "roleId": 2 + }, + { + "id": 456, + "roleId": 3 + } + ] + } + }, + "removeUsers": { + "summary": "Remove users from team", + "value": { + "action": "remove", + "users": [ + { + "id": 123 + } + ] + } + }, + "replaceUsers": { + "summary": "Replace all users on the team with the provided users", + "value": { + "action": "update", + "users": [ + { + "id": 123, + "roleId": 3 + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team users updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 1 + }, + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "User ID" + }, + "roleId": { + "type": "integer", + "description": "Role ID" + } + } + }, + "description": "Updated list of team users" + } + } + }, + "examples": { + "updatedTeamUsers": { + "value": { + "id": 1, + "users": [ + { + "userId": 123, + "roleId": 2 + }, + { + "userId": 456, + "roleId": 3 + }, + { + "userId": 789, + "roleId": 2 + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidRequestBody": { + "value": { + "message": "Invalid request body: action is required", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamRolesManagedByIDP": { + "value": { + "message": "Team roles must be managed via the identity provider.", + "code": 2001 + } + }, + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to edit this team.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/projects": { + "get": { + "operationId": "getTeamProjects", + "description": "Get a paginated list of projects for a team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter projects by title", + "schema": { + "type": "string" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort order for the projects by title", + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of team projects", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Title of the project" + }, + "locator": { + "type": "string", + "description": "Locator of the project" + } + }, + "required": [ + "title", + "locator" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of team projects" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "teamProjects": { + "value": { + "results": [ + { + "title": "Project 1", + "locator": "custom+1/project1" + }, + { + "title": "Project 2", + "locator": "custom+2/project2" + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidPage": { + "value": { + "message": "Parse error: expected undefined | positive number at root.page but found \"not-a-number\"", + "code": 2003 + } + }, + "InvalidPageSize": { + "value": { + "message": "Parse error: expected undefined | positive number at root.pageSize but found \"not-a-number\"", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "You do not have permission to view this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateTeamProjects", + "description": "Update team projects by adding, removing, or replacing projects assigned to the team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "action" + ], + "properties": { + "action": { + "type": "string", + "enum": [ + "add", + "remove", + "replace" + ], + "description": "Action to perform on team projects", + "example": "add" + }, + "projects": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of project locators", + "example": [ + "git+github.com/example/project1", + "git+github.com/example/project2" + ] + }, + { + "type": "string", + "enum": [ + "all" + ], + "description": "Add all projects in the organization to the team", + "example": "all" + } + ], + "description": "Projects to add, remove, or replace (can be array of locators or \"all\")" + }, + "filters": { + "type": "object", + "description": "Filter criteria to select projects when not specifying explicit project list", + "properties": { + "title": { + "type": "string", + "description": "Filter by project title", + "example": "my-project" + }, + "labels": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Filter by label IDs", + "example": [ + 1, + 2, + 3 + ] + }, + "type": { + "type": "string", + "description": "Filter by project type", + "example": "container" + }, + "lastRevisionWithin": { + "type": "string", + "description": "Filter by last revision date", + "example": "30d" + }, + "isPublic": { + "type": "boolean", + "description": "Filter by public/private status", + "example": true + } + } + } + } + }, + "examples": { + "addProjects": { + "summary": "Add specific projects to team", + "value": { + "action": "add", + "projects": [ + "git+github.com/example/project1", + "git+github.com/example/project2" + ] + } + }, + "addAllProjects": { + "summary": "Add all projects to team", + "value": { + "action": "add", + "projects": "all" + } + }, + "removeProjects": { + "summary": "Remove projects from team", + "value": { + "action": "remove", + "projects": [ + "git+github.com/example/project1" + ] + } + }, + "replaceWithFiltered": { + "summary": "Replace team projects using filters", + "value": { + "action": "replace", + "filters": { + "title": "frontend", + "labels": [ + 1, + 2 + ] + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team projects updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 1 + }, + "projects": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Updated list of project locators assigned to the team" + } + } + }, + "examples": { + "updatedTeamProjects": { + "value": { + "id": 1, + "projects": [ + "git+github.com/example/project1", + "git+github.com/example/project2", + "git+github.com/example/project3" + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "MissingParameters": { + "value": { + "message": "Missing the projects or filter parameters.", + "code": 2003 + } + }, + "NoMatchingProjects": { + "value": { + "message": "There are no projects that match with the filter criteria", + "code": 2003 + } + }, + "InvalidTeamId": { + "value": { + "message": "Team ID is required and must be a number.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientAddPermissions": { + "value": { + "message": "You are not permitted to add projects to this team.", + "code": 2001 + } + }, + "InsufficientRemovePermissions": { + "value": { + "message": "You are not permitted to remove projects from this team.", + "code": 2001 + } + }, + "InsufficientReplacePermissions": { + "value": { + "message": "You are not permitted to set the projects in this team.", + "code": 2001 + } + }, + "InsufficientProjectPermissions": { + "value": { + "message": "You are not permitted to add all selected projects to team \"Engineering\".", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/release-groups": { + "get": { + "operationId": "getTeamReleaseGroups", + "description": "Get a paginated list of Release Groups for a team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter Release Groups by title", + "schema": { + "type": "string" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort order for the Release Groups by title", + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of team Release Groups", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Title of the Release Group" + }, + "id": { + "type": "integer", + "description": "ID of the Release Group" + } + }, + "required": [ + "title", + "id" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of team release groups" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "teamReleaseGroups": { + "value": { + "results": [ + { + "title": "Release Group 1", + "id": 1 + }, + { + "title": "Release Group 2", + "id": 2 + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidPage": { + "value": { + "message": "Parse error: expected undefined | positive number at root.page but found \"not-a-number\"", + "code": 2003 + } + }, + "InvalidPageSize": { + "value": { + "message": "Parse error: expected undefined | positive number at root.pageSize but found \"not-a-number\"", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "You do not have permission to view this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "addReleaseGroupsToTeam", + "description": "Add release groups to a team. All projects in the release groups must already be assigned to the team.", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ids" + ], + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Array of release group IDs to add to the team", + "example": [ + 1, + 2, + 3 + ] + } + } + }, + "examples": { + "addReleaseGroups": { + "value": { + "ids": [ + 1, + 2, + 3 + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Release groups added to team successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 1 + }, + "releaseGroups": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Updated list of release group IDs assigned to the team" + } + } + }, + "examples": { + "updatedTeamReleaseGroups": { + "value": { + "id": 1, + "releaseGroups": [ + 1, + 2, + 3, + 4, + 5 + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "EmptyRequestBody": { + "value": { + "message": "Empty request body.", + "code": 2003 + } + }, + "ProjectNotInTeam": { + "value": { + "message": "The release group \"My Release Group\" has a project (locator: \"git+github.com/example/project\") that has not yet been added to this team.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to add release groups to this team.", + "code": 2001 + } + }, + "InsufficientReleaseGroupPermissions": { + "value": { + "message": "You are not permitted to add all selected release groups to this team.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "removeReleaseGroupsFromTeam", + "description": "Remove release groups from a team", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ids" + ], + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Array of release group IDs to remove from the team", + "example": [ + 1, + 2 + ] + } + } + }, + "examples": { + "removeReleaseGroups": { + "value": { + "ids": [ + 1, + 2 + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Release groups removed from team successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 1 + }, + "releaseGroups": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Updated list of release group IDs assigned to the team" + } + } + }, + "examples": { + "updatedTeamReleaseGroups": { + "value": { + "id": 1, + "releaseGroups": [ + 3, + 4, + 5 + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "EmptyRequestBody": { + "value": { + "message": "Empty request body.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to remove release groups from this team.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/addable-projects-and-release-groups": { + "get": { + "operationId": "getAddableTeamProjectsAndReleaseGroups", + "description": "Get a paginated list of projects and Release Groups that are not in the team and can be added.", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter projects and Release Groups by title", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of projects and Release Groups that can be added to the team", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Locator of the project or stringified Release Group ID" + }, + "title": { + "type": "string", + "description": "Title of the project or Release Group" + }, + "type": { + "type": "string", + "description": "Type of the project or Release Group", + "enum": [ + "project", + "release_group" + ] + } + }, + "required": [ + "id", + "title", + "type" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of projects and Release Groups that can be added to the team" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "addableProjectsAndReleaseGroups": { + "value": { + "results": [ + { + "id": "1", + "title": "Project 1", + "type": "project" + }, + { + "id": "2", + "title": "Release Group 1", + "type": "release_group" + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidPage": { + "value": { + "message": "Parse error: expected undefined | positive number at root.page but found \"not-a-number\"", + "code": 2003 + } + }, + "InvalidPageSize": { + "value": { + "message": "Parse error: expected undefined | positive number at root.pageSize but found \"not-a-number\"", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "ForbiddenTeam": { + "value": { + "message": "You do not have permission to view this team.", + "code": 2005 + } + }, + "ForbiddenEdit": { + "value": { + "message": "You do not have permission to add projects or release groups to this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/{id}/release-groups/{releaseGroupId}/addable-projects": { + "get": { + "operationId": "getAddableProjectsFromReleaseGroup", + "description": "Get a list of projects that are in the Release Group but are not in the team.", + "tags": [ + "Teams" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team", + "schema": { + "type": "integer" + } + }, + { + "name": "releaseGroupId", + "in": "path", + "required": true, + "description": "ID of the Release Group", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of projects and Release Groups that can be added to the team", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Locator of the project or stringified Release Group ID" + }, + "title": { + "type": "string", + "description": "Title of the project or Release Group" + }, + "type": { + "type": "string", + "description": "Type of the project or Release Group", + "enum": [ + "project", + "release_group" + ] + } + }, + "required": [ + "id", + "title", + "type" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of projects and Release Groups that can be added to the team" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "addableProjectsAndReleaseGroups": { + "value": { + "results": [ + { + "id": "1", + "title": "Project 1", + "type": "project" + }, + { + "id": "2", + "title": "Release Group 1", + "type": "release_group" + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamId": { + "value": { + "message": "Invalid team ID specified in request.", + "code": 2003 + } + }, + "InvalidReleaseGroupId": { + "value": { + "message": "Invalid release group ID specified in request.", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "You do not have permission to add projects or release groups to this team.", + "code": 2005 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "NotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/groups": { + "get": { + "operationId": "getTeamGroups", + "description": "Get all team groups in your organization", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "name": { + "type": "string", + "description": "Team group name", + "example": "Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for members", + "example": 2 + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 10 + }, + "name": { + "type": "string", + "description": "Team name", + "example": "Frontend Team" + }, + "numProjects": { + "type": "integer", + "description": "Number of projects and release groups assigned to this team", + "example": 5 + } + } + }, + "description": "Teams within this team group" + }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "User ID", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID", + "example": 2 + } + } + }, + "description": "Members of this team group" + } + } + } + }, + "examples": { + "teamGroups": { + "value": [ + { + "id": 1, + "name": "Engineering Team Group", + "defaultRoleId": 2, + "teams": [ + { + "id": 10, + "name": "Frontend Team", + "numProjects": 5 + }, + { + "id": 11, + "name": "Backend Team", + "numProjects": 8 + } + ], + "members": [ + { + "userId": 123, + "roleId": 2 + }, + { + "userId": 456, + "roleId": 3 + } + ] + }, + { + "id": 2, + "name": "Security Team Group", + "defaultRoleId": 2, + "teams": [ + { + "id": 15, + "name": "AppSec Team", + "numProjects": 3 + } + ], + "members": [ + { + "userId": 789, + "roleId": 2 + } + ] + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createTeamGroup", + "description": "Create a new team group", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "defaultRoleId" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of the team group", + "example": "Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for team group members", + "example": 2 + } + } + }, + "examples": { + "createTeamGroup": { + "value": { + "name": "Engineering Team Group", + "defaultRoleId": 2 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team group created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "name": { + "type": "string", + "description": "Team group name", + "example": "Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for members", + "example": 2 + } + } + }, + "examples": { + "createdTeamGroup": { + "value": { + "id": 1, + "name": "Engineering Team Group", + "defaultRoleId": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidRequestBody": { + "value": { + "message": "Invalid request body: name is required", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to create team groups.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/groups/{id}": { + "get": { + "operationId": "getTeamGroupById", + "description": "Get detailed information about a team group by ID, including teams and members", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "name": { + "type": "string", + "description": "Team group name", + "example": "Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for members", + "example": 2 + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 10 + }, + "name": { + "type": "string", + "description": "Team name", + "example": "Frontend Team" + }, + "numProjects": { + "type": "integer", + "description": "Number of projects and release groups assigned to this team", + "example": 5 + } + } + }, + "description": "Teams within this team group" + }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "User ID", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID", + "example": 2 + }, + "username": { + "type": "string", + "description": "Username", + "example": "john.doe" + }, + "email": { + "type": "string", + "description": "Email address", + "example": "john.doe@example.com" + } + } + }, + "description": "Members of this team group with user details" + } + } + }, + "examples": { + "teamGroupDetails": { + "value": { + "id": 1, + "name": "Engineering Team Group", + "defaultRoleId": 2, + "teams": [ + { + "id": 10, + "name": "Frontend Team", + "numProjects": 5 + }, + { + "id": 11, + "name": "Backend Team", + "numProjects": 8 + } + ], + "members": [ + { + "userId": 123, + "roleId": 2, + "username": "john.doe", + "email": "john.doe@example.com" + }, + { + "userId": 456, + "roleId": 3, + "username": "jane.smith", + "email": "jane.smith@example.com" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateTeamGroup", + "description": "Update a team group by ID", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group to update", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "defaultRoleId" + ], + "properties": { + "name": { + "type": "string", + "description": "New name for the team group", + "example": "Updated Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for team group members", + "example": 3 + } + } + }, + "examples": { + "updateTeamGroup": { + "value": { + "name": "Updated Engineering Team Group", + "defaultRoleId": 3 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team group updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "name": { + "type": "string", + "description": "Team group name", + "example": "Updated Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for members", + "example": 3 + }, + "autoAddUsers": { + "type": "boolean", + "description": "Whether to automatically add users", + "example": true + }, + "uniqueIdentifier": { + "type": "string", + "description": "Unique identifier", + "example": "eng-team-group" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Creation timestamp", + "example": "2020-01-01T00:00:00Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Last update timestamp", + "example": "2023-01-01T00:00:00Z" + } + } + }, + "examples": { + "updatedTeamGroup": { + "value": { + "id": 1, + "name": "Updated Engineering Team Group", + "defaultRoleId": 3, + "autoAddUsers": true, + "uniqueIdentifier": "eng-team-group", + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2023-01-01T00:00:00Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + }, + "InvalidRequestBody": { + "value": { + "message": "Invalid request body: name is required", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to update this team group.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteTeamGroup", + "description": "Delete a team group by ID. This will remove all team associations but will not delete the individual teams.", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group to delete", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Team group deleted successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to delete this team group.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team group not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/groups/{id}/teams": { + "post": { + "operationId": "addTeamsToTeamGroup", + "description": "Add teams to a team group", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "teamIds" + ], + "properties": { + "teamIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Array of team IDs to add to the team group", + "example": [ + 10, + 11, + 12 + ] + } + } + }, + "examples": { + "addTeams": { + "value": { + "teamIds": [ + 10, + 11, + 12 + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Teams added to team group successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "name": { + "type": "string", + "description": "Team group name", + "example": "Engineering Team Group" + }, + "defaultRoleId": { + "type": "integer", + "description": "Default role ID for members", + "example": 2 + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team ID", + "example": 10 + }, + "name": { + "type": "string", + "description": "Team name", + "example": "Frontend Team" + }, + "numProjects": { + "type": "integer", + "description": "Number of projects and release groups assigned to this team", + "example": 5 + } + } + }, + "description": "Updated list of teams within this team group" + }, + "members": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "User ID", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID", + "example": 2 + } + } + }, + "description": "Members of this team group" + } + } + }, + "examples": { + "updatedTeamGroup": { + "value": { + "id": 1, + "name": "Engineering Team Group", + "defaultRoleId": 2, + "teams": [ + { + "id": 10, + "name": "Frontend Team", + "numProjects": 5 + }, + { + "id": 11, + "name": "Backend Team", + "numProjects": 8 + }, + { + "id": 12, + "name": "DevOps Team", + "numProjects": 3 + } + ], + "members": [ + { + "userId": 123, + "roleId": 2 + }, + { + "userId": 456, + "roleId": 2 + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + }, + "InvalidRequestBody": { + "value": { + "message": "Invalid request body: teamIds is required", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to add teams to this team group.", + "code": 2001 + } + }, + "InsufficientTeamPermissions": { + "value": { + "message": "You are not permitted to edit all of the selected teams.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/groups/{id}/teams/{teamId}": { + "delete": { + "operationId": "removeTeamFromTeamGroup", + "description": "Remove a specific team from a team group", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group", + "schema": { + "type": "integer" + } + }, + { + "name": "teamId", + "in": "path", + "required": true, + "description": "ID of the team to remove from the team group", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Team removed from team group successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + }, + "InvalidTeamId": { + "value": { + "message": "Invalid team ID: must be a number", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InsufficientPermissions": { + "value": { + "message": "You are not permitted to delete this team group.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team group not found.", + "code": 2004 + } + }, + "TeamNotInGroup": { + "value": { + "message": "Team is not part of team group.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/teams/groups/{id}/users": { + "put": { + "operationId": "updateTeamGroupUsers", + "description": "Update team group users by adding, removing, or replacing user roles in the team group", + "tags": [ + "Team Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "ID of the team group", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "action", + "users" + ], + "properties": { + "action": { + "type": "string", + "enum": [ + "add", + "remove", + "replace" + ], + "description": "Action to perform on team group users", + "example": "add" + }, + "users": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "description": "ID of the user", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID for the user (required for add and replace actions)", + "example": 2 + } + } + }, + "description": "List of users to add, remove, or replace" + } + } + }, + "examples": { + "addUsers": { + "summary": "Add users to team group", + "value": { + "action": "add", + "users": [ + { + "id": 123, + "roleId": 2 + }, + { + "id": 456, + "roleId": 3 + } + ] + } + }, + "removeUsers": { + "summary": "Remove users from team group", + "value": { + "action": "remove", + "users": [ + { + "id": 123 + } + ] + } + }, + "replaceUsers": { + "summary": "Replace all users on the team group with the provided users", + "value": { + "action": "replace", + "users": [ + { + "id": 123, + "roleId": 3 + }, + { + "id": 789, + "roleId": 2 + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team group users updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Team group ID", + "example": 1 + }, + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "example": 123 + }, + "roleId": { + "type": "integer", + "description": "Role ID", + "example": 2 + } + } + }, + "description": "Updated list of team group users" + } + } + }, + "examples": { + "updatedTeamGroupUsers": { + "value": { + "id": 1, + "users": [ + { + "id": 123, + "roleId": 2 + }, + { + "id": 456, + "roleId": 3 + }, + { + "id": 789, + "roleId": 2 + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidTeamGroupId": { + "value": { + "message": "Invalid team group ID: must be a number", + "code": 2003 + } + }, + "InvalidRequestBody": { + "value": { + "message": "Invalid request body: action is required", + "code": 2003 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamRolesManagedByIDP": { + "value": { + "message": "Team roles must be managed via the identity provider.", + "code": 2001 + } + }, + "InsufficientPermissions": { + "value": { + "message": "You do not have permission to edit this team group.", + "code": 2001 + } + }, + "FeatureNotEnabled": { + "value": { + "message": "Team groups feature is not enabled for this organization.", + "code": 2001 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "TeamGroupNotFound": { + "value": { + "message": "Team not found.", + "code": 2004 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/projects": { + "get": { + "operationId": "getProjects", + "description": "Fetch the list of projects based on provided filters.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "title_asc", + "title_desc", + "issues-total_asc", + "issues-total_desc", + "latest-scan_asc", + "latest-scan_desc", + "last-analyzed_asc", + "last-analyzed_desc", + "issues-licensing_asc", + "issues-licensing_desc", + "issues-security_asc", + "issues-security_desc", + "issues-quality_asc", + "issues-quality_desc" + ] + }, + "description": "The category to order the results by and sort direction." + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 20 + } + }, + { + "name": "title", + "in": "query", + "description": "Filter by project name.", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Filter by project type.", + "schema": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + } + }, + { + "name": "isPublic", + "in": "query", + "description": "Filter by project being public or private.", + "schema": { + "type": "boolean" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "Filter by project labels.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "teamId[]", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "lastRevisionWithin", + "in": "query", + "description": "Filter by last revision analyzed within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "locators[]", + "in": "query", + "description": "Filter by project locators (exact match).", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "includeSharedProjects", + "in": "query", + "description": "Include shared projects.", + "schema": { + "type": "boolean" + } + }, + { + "name": "onlyIncludeSharedProjects", + "in": "query", + "description": "Only show projects that have been shared with other organizations.", + "schema": { + "type": "boolean" + } + }, + { + "name": "url", + "in": "query", + "description": "Filter by a project's URL.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "total": { + "type": "integer" + }, + "projects": { + "type": "array", + "items": [ + [ + [ + { + "type": "object", + "required": [ + "id", + "title", + "branch", + "type", + "public", + "teams" + ], + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + }, + "public": { + "type": "boolean" + }, + "url": { + "type": "string" + }, + "scanned": { + "type": "string", + "format": "date-time" + }, + "lastAnalyzed": { + "type": "string", + "format": "date-time" + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "uniqueId": { + "type": [ + "string", + "null" + ] + }, + "teamType": { + "type": "string", + "enum": [ + "team", + "team_group" + ] + } + } + } + }, + "latestRevision": { + "type": "object", + "required": [ + "locator" + ], + "properties": { + "locator": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "latestBuildStatus": { + "type": "string", + "enum": [ + "running", + "succeeded", + "failed" + ] + } + } + }, + { + "type": "object", + "required": [ + "id", + "title", + "branch", + "type", + "public", + "labels", + "teams", + "issues" + ], + "properties": { + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "total": { + "type": "integer" + }, + "licensing": { + "type": "integer" + }, + "security": { + "type": "integer" + }, + "quality": { + "type": "integer" + } + } + } + } + } + } + ], + { + "type": "object", + "required": [ + "id", + "title", + "branch", + "type", + "public", + "labels", + "teams", + "issues", + "labels" + ], + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ] + ] + } + } + }, + "examples": { + "success": { + "value": { + "projects": [ + { + "id": "custom+123/test-project-2025", + "url": "https://test.com/test-project-2025", + "title": "test-project-2025", + "branch": "develop", + "version": "test-version-01", + "type": "provided", + "public": false, + "scanned": "2025-05-22T17:41:36.644Z", + "lastAnalyzed": "2025-05-22T17:41:05.213Z", + "issues": { + "total": 10, + "licensing": 5, + "security": 3, + "quality": 2 + }, + "labels": [], + "teams": [], + "originOrganizationName": null, + "latestRevision": { + "locator": "custom+123/test-project-2025$test-version-01", + "message": "May 20th 2025, 5:16 pm +00:00" + }, + "latestBuildStatus": "succeeded" + } + ] + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProjects", + "description": "Delete projects from an organization.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Filter by project name.", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Filter by project type.", + "schema": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + } + }, + { + "name": "isPublic", + "in": "query", + "description": "Filter by project being public or private.", + "schema": { + "type": "boolean" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "Filter by project labels.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "teamId[]", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "lastRevisionWithin", + "in": "query", + "description": "Filter by last revision analyzed within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "locators", + "in": "query", + "description": "The list of locators for the projects to delete. If \"all\" is provided, then all projects that meet the provided filters will be deleted.\n", + "schema": { + "oneOf": [ + { + "type": "string", + "enum": [ + "all" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/projects/summary": { + "get": { + "operationId": "getProjectsSummary", + "description": "Summary information about the number of projects and release groups.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "summary": { + "type": "object", + "properties": { + "projects": { + "type": "integer" + }, + "releaseGroups": { + "type": "integer" + } + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/projects/labels": { + "put": { + "operationId": "updateProjectsLabels", + "description": "Apply a label to one to many projects.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "labelId", + "in": "query", + "required": true, + "description": "The ID of the label you want to apply to projects.", + "schema": { + "type": "number" + } + }, + { + "name": "locators", + "in": "query", + "required": true, + "description": "The list of locators for the projects to update. If \"all\" is provided, then all projects that meet the provided filters will have the label applied.\n", + "schema": { + "oneOf": [ + { + "type": "string", + "enum": [ + "all" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + { + "name": "title", + "in": "query", + "description": "Filter by project name.", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Filter by project type.", + "schema": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + } + }, + { + "name": "isPublic", + "in": "query", + "description": "Filter by project being public or private.", + "schema": { + "type": "boolean" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "Filter by project labels.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "teamId[]", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "lastRevisionWithin", + "in": "query", + "description": "Filter by last revision analyzed within N days.", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": {}, + "description": "An object detailing failures when applying the label. The keys are locators of projects that failed. The values are error messages. If it is empty, everything succeeded.\n" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/projects/policy": { + "put": { + "operationId": "updateProjectsPolicies", + "description": "Update the policy for one to many projects.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "policyId", + "in": "query", + "required": true, + "description": "The ID of the policy you want to apply to projects.", + "schema": { + "type": "number" + } + }, + { + "name": "locators", + "in": "query", + "required": true, + "description": "The list of locators for the projects to update. If \"all\" is provided, then all projects that meet the provided filters will have the policy applied.\n", + "schema": { + "oneOf": [ + { + "type": "string", + "enum": [ + "all" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + { + "name": "title", + "in": "query", + "description": "Filter by project name.", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Filter by project type.", + "schema": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + } + }, + { + "name": "isPublic", + "in": "query", + "description": "Filter by project being public or private.", + "schema": { + "type": "boolean" + } + }, + { + "name": "labels[]", + "in": "query", + "description": "Filter by project labels.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "teamId[]", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "lastRevisionWithin", + "in": "query", + "description": "Filter by last revision analyzed within N days.", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": {}, + "description": "An object detailing failures when applying the label. The keys are locators of projects that failed. The values are error messages. If it is empty, everything succeeded.\n" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/projects/{locator}/release-groups": { + "get": { + "operationId": "listReleaseGroupsForProject", + "description": "Returns all of the release groups that this project is a part of.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the project", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "releaseGroupId": { + "type": "number" + }, + "releaseGroupTitle": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp when the release group was created" + }, + "revisions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "revisionId": { + "type": "string" + }, + "releases": { + "type": "array", + "items": { + "type": "object", + "properties": { + "releaseId": { + "type": "number" + }, + "releaseTitle": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Project not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/release-groups": { + "get": { + "operationId": "getReleaseGroups", + "description": "Fetch the list of release groups based on provided filters.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "title_asc", + "title_desc", + "issues-total_asc", + "issues-total_desc", + "latest-scan_asc", + "latest-scan_desc" + ] + }, + "description": "The category to order the results by and sort direction." + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "title", + "in": "query", + "description": "Filter by release group name.", + "schema": { + "type": "string" + } + }, + { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned release groups.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "lastRevisionWithin", + "in": "query", + "description": "Filter by last revision analyzed within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "isPublic", + "in": "query", + "description": "Filter by whether the release group is public on the portal.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Okay", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "total": { + "type": "integer" + }, + "releaseGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "publicOnPortal": { + "type": "boolean" + }, + "scanned": { + "type": "string", + "format": "date-time" + }, + "issues": { + "type": "integer" + }, + "projects": { + "type": "integer" + } + } + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteReleaseGroups", + "description": "Delete release groups from an organization.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Filter by release group name.", + "schema": { + "type": "string" + } + }, + { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned release groups.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + }, + { + "name": "ids", + "in": "query", + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "integer" + } + }, + { + "type": "string", + "enum": [ + "all" + ] + } + ] + }, + "description": "The list of ids for the release groups to delete. If \"all\" is provided, then all release groups that meet the provided filters will be deleted.\n" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/policy": { + "put": { + "operationId": "updateReleaseGroupsPolicies", + "description": "Update a policy for one to many release groups.", + "tags": [ + "Projects" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "policyId", + "in": "query", + "required": true, + "description": "The ID of the policy you want to apply to projects.", + "schema": { + "type": "number" + } + }, + { + "name": "ids", + "in": "query", + "required": true, + "description": "The list of IDs for the release groups to update. If \"all\" is provided, then all release groups that meet the provided filters will have the label applied.\n", + "schema": { + "oneOf": [ + { + "type": "string", + "enum": [ + "all" + ] + }, + { + "type": "array", + "items": { + "type": "number" + } + } + ] + } + }, + { + "name": "title", + "in": "query", + "description": "Filter by release group name.", + "schema": { + "type": "string" + } + }, + { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned release groups.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + { + "name": "latestScan", + "in": "query", + "description": "Filter by last policy scan within N days.", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/packages/package-managers": { + "get": { + "operationId": "getPackagesPackageManagers", + "description": "Fetch the list of packages managers used by your organization. If none are used/can't be found, the full list of package managers is returned.", + "tags": [ + "Package Observability" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/packages/package-locators": { + "get": { + "operationId": "getPackagesPackageLocators", + "description": "Fetch the list of packages locators used by your organization.", + "tags": [ + "Package Observability" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "packageLocator", + "in": "query", + "description": "Filter locators to those partially matching the specified locator. For example, \"foo\" will match \"foo\", \"foobar\", and \"bazfoobar\".", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "count", + "in": "query", + "description": "The number of results to return.", + "required": false, + "schema": { + "type": "integer", + "minimum": 1 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "npm+foo", + "git+bar" + ] + }, + "pageSize": { + "type": "integer", + "example": 2 + }, + "page": { + "type": "integer", + "example": 1 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/packages/package-summary": { + "get": { + "operationId": "getPackagesPackageSummary", + "description": "Fetch the total package count and the last cache date for your organization.", + "tags": [ + "Package Observability" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "number", + "examples": [ + 100 + ] + }, + "lastCacheDate": { + "type": "string", + "format": "date-time", + "examples": [ + "2023-09-21T21:48:36.396Z" + ] + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/packages/report": { + "get": { + "operationId": "getPackageIndexExport", + "description": "Request an export of the package index with the applied set of filters. The export will be generated asynchronously and a link to the export will be emailed to you.", + "tags": [ + "Package Observability" + ], + "parameters": [ + { + "name": "fetchers", + "in": "query", + "description": "Filter packages to those from the specified fetchers. For example, fetchers[0]=npm&fetchers[1]=apk will match all NPM packages and all APK packages.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "apk", + "bower", + "cargo", + "cart", + "comp", + "conda", + "cpan", + "cran", + "deb", + "gem", + "git", + "go", + "hackage", + "hex", + "mvn", + "npm", + "nuget", + "pip", + "pod", + "pub", + "rpm", + "rpm-generic", + "swift" + ] + } + } + }, + { + "name": "packageName", + "in": "query", + "description": "Filter results to only packages with the specified name. Supports partial matches. For example \"foo\" will match \"foo\", \"foobar\", and \"foo-bar\".", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "depth", + "in": "query", + "description": "Filter results to only include packages which are direct or transitive dependencies of your projects.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "transitive" + ] + } + } + }, + { + "name": "labels", + "in": "query", + "description": "Filter packages to those belonging to your projects with the specified labels.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "projectName", + "in": "query", + "description": "Filter packages to only one of your specific projects. Exact match only.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sources", + "in": "query", + "description": "Filter packages to those belonging to your projects from the specified set of sources", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "visibility", + "in": "query", + "description": "Filter results to your projects which are public or private", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "public", + "private" + ] + } + } + }, + { + "name": "blockType", + "in": "query", + "description": "Filter packages to include only packages that do or do not have packages as dependencies which are blocked by your organization", + "required": false, + "schema": { + "type": "string", + "enum": [ + "has_blocked_packages", + "no_blocked_packages" + ] + } + }, + { + "name": "cve", + "in": "query", + "description": "Filter packages to those with vulnerabilities that have specific Common Vulnerabilities and Exposures (CVE) identifiers", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "cwes", + "in": "query", + "description": "Filter packages to those with vulnerabilities that have specific Common Weakness Enumeration (CWE) identifiers", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "locators", + "in": "query", + "description": "Filter packages to those with specific package locators (exact match only)", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "fixTypes", + "in": "query", + "description": "Filter packages to those with vulnerabilities that either have or do not have a fix available", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "severities", + "in": "query", + "description": "Filter packages by severity levels of issues", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "teamIds", + "in": "query", + "description": "Filter packages to just those owned by the specified teams. Specify the string \"null\" to filter packages that are not owned by any team.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "number" + }, + "nullable": true + } + } + ], + "responses": { + "201": { + "description": "The report generation task was created successfully. This does not mean the job completed successfully -- when the job is complete, you will receive an email with a link to download the report.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "task": { + "type": "object", + "properties": { + "task": { + "type": "string" + }, + "jobToken": { + "type": "string" + } + } + }, + "target": { + "type": "string", + "description": "Email address where the report link will be sent" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/packages": { + "get": { + "operationId": "getPackages", + "description": "Retrieve the number of projects that a dependency is used in and how many versions of it are blocked. This endpoint is paginated.", + "tags": [ + "Package Observability" + ], + "parameters": [ + { + "name": "fetchers", + "in": "query", + "description": "Filter packages to those from the specified fetchers. For example, fetchers[0]=npm&fetchers[1]=apk will match all NPM packages and all APK packages.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "apk", + "bower", + "cargo", + "cart", + "comp", + "conda", + "cpan", + "cran", + "deb", + "gem", + "git", + "go", + "hackage", + "hex", + "mvn", + "npm", + "nuget", + "pip", + "pod", + "pub", + "rpm", + "rpm-generic", + "swift" + ] + } + } + }, + { + "name": "packageName", + "in": "query", + "description": "Filter results to only packages with the specified name. Supports partial matches. For example \"foo\" will match \"foo\", \"foobar\", and \"foo-bar\".", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "depth", + "in": "query", + "description": "Filter results to only include packages which are direct or transitive dependencies of your projects.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "transitive" + ] + } + } + }, + { + "name": "labels", + "in": "query", + "description": "Filter packages to those belonging to your projects with the specified labels.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "projectName", + "in": "query", + "description": "Filter packages to only one of your specific projects. Exact match only.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sources", + "in": "query", + "description": "Filter packages to those belonging to your projects from the specified set of sources", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "visibility", + "in": "query", + "description": "Filter results to your projects which are public or private", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "public", + "private" + ] + } + } + }, + { + "name": "blockType", + "in": "query", + "description": "Filter packages to include only packages that do or do not have packages as dependencies which are blocked by your organization", + "required": false, + "schema": { + "type": "string", + "enum": [ + "has_blocked_packages", + "no_blocked_packages" + ] + } + }, + { + "name": "cve", + "in": "query", + "description": "Filter packages to those with vulnerabilities that have specific Common Vulnerabilities and Exposures (CVE) identifiers", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "cwes", + "in": "query", + "description": "Filter packages to those with vulnerabilities that have specific Common Weakness Enumeration (CWE) identifiers", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "fixTypes", + "in": "query", + "description": "Filter packages to those with vulnerabilities that either have or do not have a fix available", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "has_fix", + "no_fix" + ] + } + } + }, + { + "name": "severities", + "in": "query", + "description": "Filter packages by severity levels of issues", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + { + "name": "teamIds", + "in": "query", + "description": "Filter packages to just those owned by the specified teams. Specify the string \"null\" to filter packages that are not owned by any team.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "number" + }, + "nullable": true + } + }, + { + "name": "locators", + "in": "query", + "description": "Filter packages by the specified dependency project locators without revision / version data. Locators are unique identifiers for packages in the FOSSA system. Exact matches only.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": "locators[0]=npm+corejs" + }, + { + "name": "page", + "in": "query", + "description": "The page number to retrieve", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "in": "query", + "description": "The number of results to return per page", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "sort", + "in": "query", + "description": "The field to sort by", + "required": false, + "schema": { + "type": "string", + "enum": [ + "match", + "alphabetical", + "usage" + ] + } + } + ], + "responses": { + "200": { + "description": "The list of package dependency locators", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "task": { + "type": "object", + "properties": { + "task": { + "type": "string" + }, + "jobToken": { + "type": "string" + } + } + }, + "target": { + "type": "string", + "description": "Email address where the report link will be sent" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/package-labels": { + "get": { + "tags": [ + "Package Labels" + ], + "operationId": "getPackageLabels", + "description": "Retrieve all of the Package Labels defined for the current organization. Note - This endpoint is not available for organizations on the Free plan.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLabels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "organizationId": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + }, + "examples": { + "packageLabels": { + "value": { + "packageLabels": [ + { + "id": 5, + "organizationId": 1, + "name": "development", + "createdAt": "2024-12-02T21:31:12.515Z", + "updatedAt": "2024-12-02T21:31:12.515Z" + }, + { + "id": 6, + "organizationId": 1, + "name": "production", + "createdAt": "2024-12-02T21:59:48.719Z", + "updatedAt": "2024-12-02T21:59:48.719Z" + } + ] + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Package Labels" + ], + "operationId": "createPackageLabel", + "description": "Create one or more new Package Labels. Note - This endpoint is not available for organizations on the Free plan.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "The names of the new Package Labels", + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + }, + "examples": { + "example": { + "value": { + "labels": [ + "development", + "production" + ] + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLabels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "organizationId": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + }, + "examples": { + "packageLabels": { + "value": { + "packageLabels": [ + { + "id": 5, + "organizationId": 1, + "name": "development", + "createdAt": "2024-12-02T21:31:12.515Z", + "updatedAt": "2024-12-02T21:31:12.515Z" + }, + { + "id": 6, + "organizationId": 1, + "name": "production", + "createdAt": "2024-12-02T21:59:48.719Z", + "updatedAt": "2024-12-02T21:59:48.719Z" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "Package Labels" + ], + "operationId": "deletePackageLabels", + "description": "Delete one or more Package Labels. Note - This endpoint is not available for organizations on the Free plan.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "description": "The IDs of the Package Labels to delete", + "items": { + "type": "integer" + } + } + }, + "required": [ + "ids" + ] + }, + "examples": { + "example": { + "value": { + "ids": [ + 1, + 293 + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/package-label-assignments": { + "get": { + "tags": [ + "Package Labels" + ], + "operationId": "getPackageLabelAssignments", + "description": "Get all Package Labels assigned to a single package.", + "parameters": [ + { + "in": "query", + "name": "filters[packageId]", + "required": false, + "schema": { + "type": "string", + "description": "The ID of the package to get labels for." + }, + "example": "npm+lodash" + }, + { + "in": "query", + "name": "filters[packageVersion]", + "required": false, + "schema": { + "type": "string", + "description": "The version of the package to get labels for or blank for all versions." + }, + "example": "4.15.0" + }, + { + "in": "query", + "name": "filters[scope]", + "required": false, + "schema": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "example": "project" + }, + { + "in": "query", + "name": "filters[scopeId]", + "required": false, + "schema": { + "type": "string", + "description": "The ID of the scope to get labels for." + }, + "example": "custom+1/my-cli-project or custom+1/my-cli-project/$revision1" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLabelAssignmentResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId" + ] + } + } + }, + "examples": { + "packageLabelAssignments": { + "value": { + "packageLabelAssignments": { + "id": 1, + "createdAt": "2024-12-02T21:31:12.515Z", + "updatedAt": "2024-12-02T21:31:12.515Z", + "organizationId": 1, + "labelId": 5, + "packageId": "npm+lodash", + "packageVersion": "4.15.0", + "scope": { + "id": 1, + "name": "project" + }, + "scopeId": "custom+1/my-cli-project" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Package Labels" + ], + "operationId": "createPackageLabelAssignments", + "description": "Assign one or more Package Labels to a single package. Note - This endpoint is not available for organizations on the Free plan.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageId": { + "type": "string", + "description": "The ID of the package to assign labels to." + }, + "packageVersion": { + "type": "string", + "description": "The version of the package to assign labels to or blank for all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "description": "The ID of the scope to assign labels to." + }, + "labelIds": { + "type": "array", + "description": "The IDs of the labels to assign to the package.", + "items": { + "type": "integer" + } + } + }, + "required": [ + "packageId", + "labels" + ] + }, + "examples": { + "example": { + "value": { + "packageId": "npm+lodash", + "packageVersion": "4.15.0", + "scope": "project", + "scopeId": "custom+1/my-cli-project", + "labelIds": [ + 1, + 2 + ] + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLabelAssignmentResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId" + ] + } + } + }, + "examples": { + "packageLabelAssignments": { + "value": { + "packageLabelAssignments": { + "id": 1, + "createdAt": "2024-12-02T21:31:12.515Z", + "updatedAt": "2024-12-02T21:31:12.515Z", + "organizationId": 1, + "labelId": 5, + "packageId": "npm+lodash", + "packageVersion": "4.15.0", + "scope": { + "id": 1, + "name": "project" + }, + "scopeId": "custom+1/my-cli-project" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "Package Labels" + ], + "operationId": "deletePackageLabelAssignments", + "description": "Remove one or more Package Labels from a single package.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "assignmentLabelIds": { + "type": "array", + "description": "The IDs of the package label assignments to delete.", + "items": { + "type": "integer" + } + } + } + }, + "examples": { + "example": { + "value": { + "assignmentLabelIds": [ + 1, + 2 + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/package-label-assignments/bulk": { + "post": { + "tags": [ + "Package Labels" + ], + "operationId": "bulkAssignPackageLabels", + "description": "Assign a single Package Label to multiple packages at once.\n\nNote - This endpoint is not available for organizations on the Free plan.\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLocators": { + "type": "array", + "description": "Array of revision locators to assign the label to. Must include the version (e.g., 'npm+lodash$4.17.21').", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "labelId": { + "type": "integer", + "description": "The ID of the label to assign to all packages." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "description": "The ID of the scope to assign labels to. Required if scope is 'project' or 'revision'." + }, + "shouldUseSpecificVersion": { + "type": "boolean", + "description": "If true, labels will apply to the specific versions provided in the packageLocators.\nIf false, labels will apply to all versions of the packages (ignoring the version part of the locator).\nDefaults to true.\n", + "default": true + } + }, + "required": [ + "packageLocators", + "labelId", + "scope" + ] + }, + "examples": { + "bulkAssignWithSpecificVersions": { + "summary": "Assign label to specific package versions", + "value": { + "packageLocators": [ + "npm+lodash$4.17.21", + "npm+react$17.0.2", + "maven+com.google.guava:guava$30.1-jre" + ], + "labelId": 1, + "scope": "org", + "shouldUseSpecificVersion": true + } + }, + "bulkAssignToAllVersions": { + "summary": "Assign label to all versions of packages", + "value": { + "packageLocators": [ + "npm+lodash$4.17.21", + "npm+react$17.0.2" + ], + "labelId": 1, + "scope": "org", + "shouldUseSpecificVersion": false + } + }, + "bulkAssignWithProjectScope": { + "summary": "Assign label with project scope", + "value": { + "packageLocators": [ + "npm+lodash$4.17.21", + "npm+react$17.0.2" + ], + "labelId": 1, + "scope": "project", + "scopeId": "custom+1/my-cli-project", + "shouldUseSpecificVersion": true + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageLabelAssignmentResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId" + ] + } + } + }, + "examples": { + "packageLabelAssignments": { + "value": { + "packageLabelAssignments": { + "id": 1, + "createdAt": "2024-12-02T21:31:12.515Z", + "updatedAt": "2024-12-02T21:31:12.515Z", + "organizationId": 1, + "labelId": 5, + "packageId": "npm+lodash", + "packageVersion": "4.15.0", + "scope": { + "id": 1, + "name": "project" + }, + "scopeId": "custom+1/my-cli-project" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request - Invalid input such as empty packageLocators array, missing required fields, or invalid scope.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden - User does not have permission to assign labels or organization is on Free plan.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "Not Found - Package label or one or more packages do not exist.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/project_group": { + "post": { + "operationId": "createReleaseGroup", + "description": "Used to create a release group. Fails if user's organization is at or over the release group limit.", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "title", + "release" + ], + "properties": { + "title": { + "type": "string" + }, + "licensingPolicyId": { + "type": "integer", + "nullable": true + }, + "securityPolicyId": { + "type": "integer", + "nullable": true + }, + "qualityPolicyId": { + "type": "integer", + "nullable": true + }, + "publicOnPortal": { + "type": "boolean", + "nullable": true + }, + "issueTrackerType": { + "type": "string", + "enum": [ + "github", + "jira" + ] + }, + "teams": { + "type": "array", + "items": { + "type": [ + "integer" + ] + } + }, + "release": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + } + } + } + } + } + } + }, + "example": { + "title": "New Release Group", + "licensingPolicyId": 1, + "securityPolicyId": 2, + "qualityPolicyId": null, + "publicOnPortal": true, + "issueTrackerType": "github", + "teams": [ + 101, + 102 + ], + "release": { + "title": "1.0.0", + "projects": [ + { + "projectId": "custom+1/my-repo", + "branch": "main", + "revisionId": "rev001" + }, + { + "projectId": "custom+1/my-other-repo", + "branch": "develop", + "revisionId": "rev002" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Created the release group", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1, + "policyId": 1, + "securityPolicyId": 1, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "maximumReleaseGroupsReached'": { + "summary": "Maximum release groups reached", + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Your organization has reached the maximum number of release groups.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "missingRequiredField": { + "summary": "Missing required field", + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Release group title is required", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Release groups are not enabled for your organization, or you do not have permission to create them", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to add a release group to all the selected teams.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + }, + "/project_group/{groupId}": { + "get": { + "operationId": "getReleaseGroupById", + "description": "Get a release group by ID", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + { + "type": "object", + "properties": { + "releases": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Release ID" + }, + "title": { + "type": "string", + "description": "Release title/version" + }, + "projectGroupId": { + "type": "integer", + "description": "The release group which this belongs to" + }, + "dependency_count": { + "type": "integer", + "description": "The count of dependencies in this release", + "nullable": true + }, + "license_count": { + "type": "integer", + "description": "The count of licenses in this release", + "nullable": true + }, + "unresolved_licensing_issue_count": { + "type": "integer", + "description": "The number of licensing issues in this release", + "nullable": true + }, + "unresolved_security_issue_count": { + "type": "integer", + "description": "The number of security issues in this release", + "nullable": true + }, + "unresolved_quality_issue_count": { + "type": "integer", + "description": "The number of quality issues in this release", + "nullable": true + }, + "publishedOnPortal": { + "description": "If this release has been published on an SBOM portal", + "type": "string", + "enum": [ + "attribution_txt", + "spdx_tagged", + "cyclonedx_json", + "spdx_json", + "cyclonedx_xml", + "pending" + ], + "nullable": true + }, + "publishedAt": { + "type": "string", + "format": "date-time", + "description": "When the release was published to the portal" + }, + "reportPath": { + "type": "string", + "description": "Path to the SBOM report for this release", + "nullable": true + }, + "publishedLicenses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of published license IDs", + "nullable": true + } + }, + "example": { + "id": 1, + "title": "1.0.0", + "projectGroupId": 1, + "dependency_count": 50, + "license_count": 10, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 3, + "unresolved_quality_issue_count": 1, + "publishedOnPortal": "cyclonedx_json", + "publishedAt": "2024-07-09T19:14:26Z", + "reportPath": "/reports/1.0.0/sbom.cyclonedx.json", + "publishedLicenses": [ + "MIT", + "Apache-2.0" + ] + } + } + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectGroupReleaseId": { + "type": "integer" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "projectId": "custom+1/github.com/myrepo", + "projectGroupReleaseId": 1, + "branch": "main", + "revisionId": "rev001", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + } + }, + "scans": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 123 + }, + "scanned_at": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + }, + "organizationId": { + "type": "integer", + "example": 1 + }, + "projectGroupReleaseId": { + "type": "integer", + "example": 123 + }, + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + } + }, + "example": { + "value": { + "id": 1, + "scanned_at": "2024-07-09T19:14:26Z", + "organizationId": 100, + "projectGroupReleaseId": 200, + "createdAt": "2024-07-09T18:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + } + } + } + } + } + ] + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z", + "releases": [ + { + "id": 1, + "title": "1.0.0", + "projectGroupId": 1, + "dependency_count": 50, + "license_count": 10, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 3, + "unresolved_quality_issue_count": 1, + "publishedOnPortal": "cyclonedx_json", + "publishedAt": "2024-07-09T19:14:26Z", + "reportPath": "/reports/1.0.0/sbom.cyclonedx.json", + "publishedLicenses": [ + "MIT", + "Apache-2.0" + ] + } + ], + "projects": [ + { + "projectId": "custom+1/github.com/myrepo", + "projectGroupReleaseId": 1, + "branch": "main", + "revisionId": "rev001", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + ], + "scans": [ + { + "id": 1, + "scanned_at": "2024-07-09T19:14:26Z", + "organizationId": 100, + "projectGroupReleaseId": 200, + "createdAt": "2024-07-09T18:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + ] + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "ProjectGroup (id: 1) not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "put": { + "operationId": "updateReleaseGroupById", + "description": "Update a given release group", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "licensingPolicyId": { + "type": "integer", + "nullable": true + }, + "securityPolicyId": { + "type": "integer", + "nullable": true + }, + "qualityPolicyId": { + "type": "integer", + "nullable": true + }, + "publicOnPortal": { + "type": "boolean", + "nullable": true + }, + "reportCustomText": { + "type": "string", + "nullable": true + } + }, + "example": { + "title": "Updated Release Group", + "licensingPolicyId": 1, + "securityPolicyId": 2, + "qualityPolicyId": 3, + "publicOnPortal": true, + "reportCustomText": null + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + "example": { + "id": 1, + "title": "Updated Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": 1003, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to edit this release group.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "ProjectGroup (id: 1) not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "delete": { + "operationId": "deleteReleaseGroupById", + "description": "Delete a given release group", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": {} + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to edit this release group.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + }, + "/project_group/{groupId}/all_projects": { + "get": { + "operationId": "getAllProjectsInReleaseGroup", + "description": "Returns a list of all of the projects in a given release group (regardless of release)", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": [ + "git+github.com/myorg/myrepo", + "git+gitlab.com/myorg/myrepo2", + "sbom+1/some-sbom-project", + "custom+1/my-cli-project", + "git+github.com/myorg/myrepo3", + "git+github.com/fossas/fossa-cli" + ] + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + }, + "/project_group/{groupId}/teams": { + "get": { + "operationId": "getAllReleaseGroupTeams", + "description": "Returns a list of all of the teams assigned to a given release group, and a totalCount", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "totalCount": { + "type": "integer" + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + } + } + }, + "example": { + "totalCount": 3, + "teams": [ + { + "id": 1, + "name": "West Coast Team" + }, + { + "id": 2, + "name": "Midwest Team" + }, + { + "id": 3, + "name": "East Coast Team" + } + ] + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/releases": { + "get": { + "operationId": "getReleaseGroupReleases", + "description": "Returns a paginated list of releases for a given release group. You must have permission to view this release group.", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "count", + "in": "query", + "schema": { + "type": "integer", + "default": 10, + "minimum": 1, + "maximum": 50 + } + }, + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "releases": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Release ID" + }, + "title": { + "type": "string", + "description": "Release title/version" + }, + "projectGroupId": { + "type": "integer", + "description": "The release group which this belongs to" + }, + "dependency_count": { + "type": "integer", + "description": "The count of dependencies in this release", + "nullable": true + }, + "license_count": { + "type": "integer", + "description": "The count of licenses in this release", + "nullable": true + }, + "unresolved_licensing_issue_count": { + "type": "integer", + "description": "The number of licensing issues in this release", + "nullable": true + }, + "unresolved_security_issue_count": { + "type": "integer", + "description": "The number of security issues in this release", + "nullable": true + }, + "unresolved_quality_issue_count": { + "type": "integer", + "description": "The number of quality issues in this release", + "nullable": true + }, + "publishedOnPortal": { + "description": "If this release has been published on an SBOM portal", + "type": "string", + "enum": [ + "attribution_txt", + "spdx_tagged", + "cyclonedx_json", + "spdx_json", + "cyclonedx_xml", + "pending" + ], + "nullable": true + }, + "publishedAt": { + "type": "string", + "format": "date-time", + "description": "When the release was published to the portal" + }, + "reportPath": { + "type": "string", + "description": "Path to the SBOM report for this release", + "nullable": true + }, + "publishedLicenses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of published license IDs", + "nullable": true + } + }, + "example": { + "id": 1, + "title": "1.0.0", + "projectGroupId": 1, + "dependency_count": 50, + "license_count": 10, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 3, + "unresolved_quality_issue_count": 1, + "publishedOnPortal": "cyclonedx_json", + "publishedAt": "2024-07-09T19:14:26Z", + "reportPath": "/reports/1.0.0/sbom.cyclonedx.json", + "publishedLicenses": [ + "MIT", + "Apache-2.0" + ] + } + } + }, + "total": { + "type": "integer" + } + } + }, + "example": { + "releases": [ + { + "id": 1, + "title": "1.0.0", + "projectGroupId": 1, + "dependency_count": 10, + "license_count": 5, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 1, + "unresolved_quality_issue_count": 0, + "publishedOnPortal": null, + "publishedAt": null, + "reportPath": null, + "publishedLicenses": null + }, + { + "id": 2, + "title": "1.1.0", + "projectGroupId": 1, + "dependency_count": 10, + "license_count": 5, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 1, + "unresolved_quality_issue_count": 0, + "publishedOnPortal": null, + "publishedAt": null, + "reportPath": null, + "publishedLicenses": null + }, + { + "id": 3, + "title": "1.2.0", + "projectGroupId": 1, + "dependency_count": 10, + "license_count": 5, + "unresolved_licensing_issue_count": 2, + "unresolved_security_issue_count": 1, + "unresolved_quality_issue_count": 0, + "publishedOnPortal": null, + "publishedAt": null, + "reportPath": null, + "publishedLicenses": null + } + ], + "total": 3 + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Invalid release group ID", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + }, + "/project_group/{groupId}/release": { + "get": { + "operationId": "deprecatedGetReleaseGroupReleases", + "description": "This endpoint is deprecated. Please use the paginated /project_group/{groupId}/releases endpoint instead.", + "deprecated": true, + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + { + "type": "object", + "properties": { + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectGroupReleaseId": { + "type": "integer" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "projectId": "custom+1/github.com/myrepo", + "projectGroupReleaseId": 1, + "branch": "main", + "revisionId": "rev001", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + } + } + } + } + ] + }, + "example": [ + { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": 1003, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z", + "projects": [] + } + ] + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "post": { + "operationId": "createReleaseGroupReleases", + "description": "Creates a new release for a given release group", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + } + } + } + } + }, + "example": { + "title": "1.2.3", + "projects": [ + { + "projectId": "git+github.com/myorg/myrepo", + "branch": "main", + "revisionId": "a0b1c3" + }, + { + "projectId": "git+github.com/myorg/other-repo", + "branch": "develop", + "revisionId": "rev0003" + }, + { + "projectId": "sbom+1/my-sbom-upload-project", + "branch": "main", + "revisionId": "rev123" + } + ] + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + "example": { + "id": 1, + "title": "New Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": 1003, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Release with title already exists", + "name": "BadRequest", + "httpStatusCode": 400 + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to edit this release group.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "ProjectGroup (id: 1) not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}": { + "get": { + "operationId": "getReleaseGroupReleaseById", + "description": "Get a specific release within a release group, by ID", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + }, + { + "type": "object", + "properties": { + "projects": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectGroupReleaseId": { + "type": "integer" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "projectId": "custom+1/github.com/myrepo", + "projectGroupReleaseId": 1, + "branch": "main", + "revisionId": "rev001", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + }, + { + "type": "object", + "properties": { + "project": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "required": [ + "id", + "title", + "branch", + "type", + "public", + "teams" + ], + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "container", + "archive", + "provided", + "autobuild", + "sbom" + ] + }, + "public": { + "type": "boolean" + }, + "url": { + "type": "string" + }, + "scanned": { + "type": "string", + "format": "date-time" + }, + "lastAnalyzed": { + "type": "string", + "format": "date-time" + }, + "teams": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "uniqueId": { + "type": [ + "string", + "null" + ] + }, + "teamType": { + "type": "string", + "enum": [ + "team", + "team_group" + ] + } + } + } + }, + "latestRevision": { + "type": "object", + "required": [ + "locator" + ], + "properties": { + "locator": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "latestBuildStatus": { + "type": "string", + "enum": [ + "running", + "succeeded", + "failed" + ] + } + } + }, + { + "latestRevision": [ + { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Normalized representation of the Locator", + "properties": { + "fetcher": { + "type": "string", + "description": "the external package manager or internal representation of one" + }, + "package": { + "type": "string", + "description": "the package name" + }, + "revision": { + "type": "string", + "description": "the version/revision of the package" + } + } + }, + "locator": { + "type": "string", + "description": "Text ID that uniquely identifies a project" + }, + "resolved": { + "type": "boolean", + "description": "Has the Revision been fully analyzed by FOSSA" + }, + "projectId": { + "type": "string", + "description": "The Project locator that the Revision belongs to" + }, + "source_type": { + "type": [ + "string", + "null" + ], + "description": "FOSSA internal representation of the source language for the given repository/project" + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message during analysis (if any)" + }, + "message": { + "type": [ + "string", + "null" + ], + "description": "Message of the revision or commit" + }, + "revision_timestamp": { + "type": [ + "string", + "null" + ], + "description": "timestamp of when the Revision was published" + }, + "latestRevisionScanId": { + "type": [ + "number", + "null" + ], + "description": "The Revision Scan ID of the latest policy scan" + }, + "latestHubbleAnalysisId": { + "type": [ + "number", + "null" + ], + "description": "The Hubble Analysis ID of the latest analysis" + }, + "createdAt": { + "type": "string", + "description": "when the Revision was added to the FOSSA Database" + }, + "updatedAt": { + "type": "string", + "description": "when the Revision was last updated in the FOSSA Database" + }, + "author": { + "type": [ + "string", + "null" + ], + "description": "The author of the Revision" + }, + "link": { + "type": [ + "string", + "null" + ], + "description": "The link associated with the Revision" + }, + "url": { + "type": [ + "string", + "null" + ], + "description": "The url associated with the Revision" + } + } + } + ] + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "example": [ + { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": 1003, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z", + "projects": [ + { + "projectId": "custom+1/github.com/myorg/myrepo", + "projectGroupReleaseId": 1, + "branch": "main", + "revisionId": "rev001", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z", + "project": [ + { + "id": "123", + "title": "Some Project", + "description": "This is a project in my organization", + "branch": "main", + "type": "provided", + "public": true, + "scanned": "2024-07-09T19:14:26Z", + "lastAnalyzed": "2024-07-09T19:14:26Z", + "latestRevision": { + "locator": "custom+1/github.com/myorg/myrepo$rev001", + "resolve": true, + "projectId": "custom+1/github.com/myorg/myrepo", + "source_type": null, + "error": null, + "message": "fix(bug): Fixes some bug", + "latestRevisionScanId": 123, + "latestHubbleAnalysisId": null, + "revision_timestamp": "2024-07-09T19:14:26Z", + "createdAt": "2024-07-09T19:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z", + "author": "fossas", + "link": null, + "url": "https://github.com/myorg/myrepo" + }, + "teams": [ + { + "id": 1, + "organizationId": 1, + "name": "Front-end Team", + "defaultRoleId": 2, + "autoAddusers": false, + "uniqueIdentifier": false, + "createdAt": "2024-06-09T19:14:26Z", + "updatedAt": "2024-06-09T19:14:26Z" + }, + { + "id": 2, + "organizationId": 1, + "name": "Back-end Team", + "defaultRoleId": 3, + "autoAddusers": false, + "uniqueIdentifier": false, + "createdAt": "2024-06-09T19:15:26Z", + "updatedAt": "2024-06-09T19:15:26Z" + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release (id: 123) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateReleaseGroupReleaseById", + "description": "Update a specific release within a release group, by ID", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "projects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "revisionId": { + "type": "string" + } + }, + "example": { + "projectId": "custom+1/org/project", + "branch": "main", + "revisionId": "rev001" + } + } + }, + "projectsToDelete": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "title" + ], + "example": { + "title": "New Release Title", + "projects": [ + { + "projectId": "custom+1/org/project", + "branch": "main", + "revisionId": "rev001" + } + ], + "projectsToDelete": [ + "custom+1/org/deleteable" + ] + } + }, + "example": { + "title": "2.0.0", + "projects": [ + { + "projectId": "custom+1/org/project", + "branch": "main", + "revisionId": "rev001" + } + ], + "projectsToDelete": [ + "custom+1/org/deleteable" + ] + } + } + } + }, + "responses": { + "200": { + "description": "The release group could not be found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "organizationId": { + "type": "integer" + }, + "policyId": { + "type": [ + "null", + "integer" + ] + }, + "securityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "qualityPolicyId": { + "type": [ + "null", + "integer" + ] + }, + "publicOnPortal": { + "type": "boolean" + }, + "reportCustomText": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "example": { + "id": 1, + "title": "My Release Group", + "organizationId": 1000, + "policyId": 1001, + "securityPolicyId": 1002, + "qualityPolicyId": null, + "publicOnPortal": true, + "customReportText": null, + "createdAt": "2024-07-09T21:51:20.671Z", + "updatedAt": "2024-07-09T21:51:20.671Z" + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No title": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Release title is required", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid projects": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Projects must be an array", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No branch on project": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Project branch is required", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No projectId on project": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Project projectId is required", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "No revisionId on project": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "Project revisionId is required", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid projectsToDelete": { + "value": { + "uuid": "e307c56c-1343-41c8-bd68-a2a1877f2632", + "code": 2003, + "message": "The \"projectsToDelete\" property must be an array.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "The requesting user is not allowed to edit this release group", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to edit this release group.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "The release group could not be found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "Release Group (id: 1) was not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "delete": { + "operationId": "deleteReleaseGroupReleaseById", + "description": "Delete a specific release within a release group, by ID", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK - No content" + }, + "403": { + "description": "The requesting user is not allowed to edit this release group", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to edit this release group.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "The release group could not be found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "Release Group (id: 1) was not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}/revisions": { + "get": { + "operationId": "getReleaseGroupReleaseRevisions", + "description": "Get the revisions for a given release", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Normalized representation of the Locator", + "properties": { + "fetcher": { + "type": "string", + "description": "the external package manager or internal representation of one" + }, + "package": { + "type": "string", + "description": "the package name" + }, + "revision": { + "type": "string", + "description": "the version/revision of the package" + } + } + }, + "locator": { + "type": "string", + "description": "Text ID that uniquely identifies a project" + }, + "resolved": { + "type": "boolean", + "description": "Has the Revision been fully analyzed by FOSSA" + }, + "projectId": { + "type": "string", + "description": "The Project locator that the Revision belongs to" + }, + "source_type": { + "type": [ + "string", + "null" + ], + "description": "FOSSA internal representation of the source language for the given repository/project" + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message during analysis (if any)" + }, + "message": { + "type": [ + "string", + "null" + ], + "description": "Message of the revision or commit" + }, + "revision_timestamp": { + "type": [ + "string", + "null" + ], + "description": "timestamp of when the Revision was published" + }, + "latestRevisionScanId": { + "type": [ + "number", + "null" + ], + "description": "The Revision Scan ID of the latest policy scan" + }, + "latestHubbleAnalysisId": { + "type": [ + "number", + "null" + ], + "description": "The Hubble Analysis ID of the latest analysis" + }, + "createdAt": { + "type": "string", + "description": "when the Revision was added to the FOSSA Database" + }, + "updatedAt": { + "type": "string", + "description": "when the Revision was last updated in the FOSSA Database" + }, + "author": { + "type": [ + "string", + "null" + ], + "description": "The author of the Revision" + }, + "link": { + "type": [ + "string", + "null" + ], + "description": "The link associated with the Revision" + }, + "url": { + "type": [ + "string", + "null" + ], + "description": "The url associated with the Revision" + } + } + }, + { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "example": "custom-license" + }, + "id": { + "type": "integer", + "example": 22493 + }, + "licenseId": { + "type": "string", + "example": "custom-license" + }, + "revisionId": { + "type": "string", + "example": "custom+1/david-CORE-3156$2024-03-28T17:34:14Z" + }, + "licenseGroupId": { + "type": "integer", + "example": 18965 + }, + "projectCorrectionId": { + "type": "string", + "nullable": true, + "example": null + }, + "ignored": { + "type": "boolean", + "example": false + }, + "url": { + "type": "string", + "nullable": true, + "example": null + }, + "text": { + "type": "string", + "nullable": true, + "example": null + }, + "copyright": { + "type": "string", + "nullable": true, + "example": null + }, + "file_count": { + "type": "integer", + "example": 1 + }, + "manual": { + "type": "boolean", + "example": false + }, + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2024-03-28T17:34:36.062Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2024-03-28T17:34:36.062Z" + } + } + } + } + } + } + ] + }, + "example": [ + { + "loc": { + "fetcher": "git", + "package": "user/project-12345", + "revision": "rev001" + }, + "locator": "git+github/user/project-12345$rev001", + "resolved": true, + "projectId": "git+github/user/project-12345", + "source_type": "CommonJSPackage", + "error": null, + "message": "Initial commit", + "revision_timestamp": "2024-03-28T17:34:36.062Z", + "latestRevisionScanId": 123456, + "latestHubbleAnalysisId": 789012, + "createdAt": "2024-03-28T17:34:36.062Z", + "updatedAt": "2024-03-28T17:34:36.062Z", + "author": "john.doe", + "link": null, + "url": null, + "licenses": [ + { + "title": "MIT", + "id": 12345, + "licenseId": "MIT", + "revisionId": "MIT", + "licenseGroupId": 123, + "ignored": false, + "projectCorrectionId": null, + "url": null, + "text": null, + "copyright": null, + "manual": false + } + ] + } + ] + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release (id: 123) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}/licenses": { + "get": { + "operationId": "getReleaseGroupReleaseLicenses", + "description": "Get the licenses for a given release", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "An object where each key is a license ID, and each value is an object representing that license", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "depth": { + "type": "integer", + "example": 1 + }, + "licenseId": { + "type": "string", + "example": "MIT" + }, + "name": { + "type": "string", + "example": "MIT License" + }, + "matches": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ] + }, + "sources": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + }, + "example": { + "value": { + "depth": 1, + "licenseId": "MIT", + "name": "MIT License", + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + } + }, + "example": { + "MIT": { + "licenseId": "MIT", + "name": "MIT License", + "depth": 1, + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + } + } + }, + "application/x-ndjson": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "depth": { + "type": "integer", + "example": 1 + }, + "licenseId": { + "type": "string", + "example": "MIT" + }, + "name": { + "type": "string", + "example": "MIT License" + }, + "matches": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ] + }, + "sources": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + }, + "example": { + "value": { + "depth": 1, + "licenseId": "MIT", + "name": "MIT License", + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + } + }, + "example": { + "MIT": { + "licenseId": "MIT", + "name": "MIT License", + "depth": 1, + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + } + } + } + } + }, + "403": { + "description": "The requesting user is not allowed to view these licenses", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "The requesting user is not part of an organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This group does not exist.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}/obligations": { + "get": { + "operationId": "getReleaseGroupReleaseObligations", + "description": "Get the license obligations for a given release", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "An object where each key is a license ID, and each value is an object representing that license", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "The description of the obligation." + }, + "license": { + "type": "string", + "description": "The license associated with the obligation." + }, + "revisions": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "A dictionary where the key is the parent locator and the value is an array of locators in which the obligation was found." + } + }, + "example": { + "summary": "An example of a license obligation", + "value": { + "license": "BSD-4-Clause", + "description": "Describes whether the original copyright must be retained.", + "revisions": { + "sbom+1/my-sbom-project": [ + "npm+svelte$1.1.1" + ], + "custom+1/my-cli-project": [ + "npm+svelte$1.1.1" + ] + } + } + } + } + }, + "example": { + "Include License": [ + { + "license": "BSD-4-Clause", + "description": "Describes whether the original copyright must be retained.", + "revisions": { + "sbom+1/my-sbom-project": [ + "npm+svelte$1.1.1" + ], + "custom+1/my-cli-project": [ + "npm+svelte$1.1.1" + ] + } + } + ] + } + } + } + } + }, + "403": { + "description": "The requesting user is not allowed to view these license obligations", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "The requesting user is not part of an organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This group does not exist.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}/scans": { + "get": { + "operationId": "getReleaseGroupReleaseScans", + "description": "Get the release scans for a given release", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 123 + }, + "scanned_at": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + }, + "organizationId": { + "type": "integer", + "example": 1 + }, + "projectGroupReleaseId": { + "type": "integer", + "example": 123 + }, + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2024-07-02T22:56:38.769Z" + } + }, + "example": { + "value": { + "id": 1, + "scanned_at": "2024-07-09T19:14:26Z", + "organizationId": 100, + "projectGroupReleaseId": 200, + "createdAt": "2024-07-09T18:14:26Z", + "updatedAt": "2024-07-09T19:14:26Z" + } + } + }, + { + "type": "object", + "properties": { + "revisionScans": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + } + ] + } + } + } + ] + }, + "example": [ + { + "id": 123, + "scanned_at": "2024-07-02T22:56:38.769Z", + "organizationId": 1, + "projectGroupReleaseId": 123, + "createdAt": "2024-07-02T22:56:38.769Z", + "updatedAt": "2024-07-02T22:56:38.769Z", + "revisionScans": [ + { + "id": 6001 + }, + { + "id": 6002 + }, + { + "id": 6003 + } + ] + } + ] + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 123) was not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release (id: 123) was not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{projectGroupReleaseId}/summary": { + "get": { + "operationId": "getReleaseGroupReleaseSummary", + "description": "Get a summary of release group issue, project and dependency counts", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "license_count": { + "type": "integer", + "example": 5 + }, + "dependency_count": { + "type": "integer", + "example": 50 + }, + "project_count": { + "type": "integer", + "example": 10 + }, + "unresolved_issue_count": { + "type": "integer", + "example": 300 + }, + "unresolved_licensing_issue_count": { + "type": "integer", + "example": 100 + }, + "unresolved_security_issue_count": { + "type": "integer", + "example": 100 + }, + "unresolved_quality_issue_count": { + "type": "integer", + "example": 100 + }, + "isSteady": { + "type": "boolean", + "example": true + } + } + }, + "example": { + "license_count": 5, + "dependency_count": 50, + "project_count": 10, + "unresolved_issue_count": 300, + "unresolved_licensing_issue_count": 100, + "unresolved_security_issue_count": 100, + "unresolved_quality_issue_count": 100, + "isSteady": true + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 123) was not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "Release Group Release Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release (id: 123) was not found", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/project_group/{groupId}/release/{releaseId}/attribution/{format}": { + "post": { + "operationId": "queueReleaseGroupAttributionReport", + "description": "Submit a Release Group attribution report for processing.", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "groupId", + "description": "The ID of the release group", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "releaseId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "format", + "required": true, + "in": "path", + "schema": { + "type": "string", + "enum": [ + "HTML", + "MD", + "PDF", + "CSV", + "TXT", + "SPDX", + "SPDX_JSON", + "CYCLONEDX_JSON", + "CYCLONEDX_XML" + ] + } + }, + { + "name": "includeDeepDependencies", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDirectDependencies", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeFOSSADependencies", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseList", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseScan", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeProjectLicense", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyrightList", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeFileMatches", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeOpenVulnerabilities", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeClosedVulnerabilities", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDependencySummary", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseHeaders", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "dependencyInfoOptions[]", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Project", + "Library", + "Authors", + "Description", + "License", + "CustomTextLicense", + "FullTextLicense", + "OtherLicenses", + "FilePath", + "Source", + "ProjectUrl", + "PackageDownloadUrl", + "DependencyPaths", + "IssueNotes" + ] + } + } + }, + { + "name": "isPublishing", + "description": "Whether to publish the report to the portal", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "taskId": { + "type": "integer" + } + } + } + } + } + }, + "400": { + "description": "BadRequest", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/project_group/attribution/{taskId}": { + "get": { + "operationId": "getReleaseGroupAttributionReportStatus", + "description": "Check the status of a Release Group attribution report.", + "tags": [ + "Release Groups" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "taskId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "taskId": { + "type": "integer" + }, + "status": { + "type": "string", + "enum": [ + "CREATED", + "ASSIGNED", + "RUNNING", + "SUCCEEDED", + "FAILED" + ] + }, + "url": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}": { + "patch": { + "operationId": "updateRevision", + "description": "Update revision metadata.", + "tags": [ + "Revisions" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "link": { + "type": "string", + "description": "New link for Revision" + }, + "url": { + "type": "string", + "description": "New url for Revision" + }, + "author": { + "type": "string", + "description": "New author for Revision" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Normalized representation of the Locator", + "properties": { + "fetcher": { + "type": "string", + "description": "the external package manager or internal representation of one" + }, + "package": { + "type": "string", + "description": "the package name" + }, + "revision": { + "type": "string", + "description": "the version/revision of the package" + } + } + }, + "locator": { + "type": "string", + "description": "Text ID that uniquely identifies a project" + }, + "resolved": { + "type": "boolean", + "description": "Has the Revision been fully analyzed by FOSSA" + }, + "projectId": { + "type": "string", + "description": "The Project locator that the Revision belongs to" + }, + "source_type": { + "type": [ + "string", + "null" + ], + "description": "FOSSA internal representation of the source language for the given repository/project" + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message during analysis (if any)" + }, + "message": { + "type": [ + "string", + "null" + ], + "description": "Message of the revision or commit" + }, + "revision_timestamp": { + "type": [ + "string", + "null" + ], + "description": "timestamp of when the Revision was published" + }, + "latestRevisionScanId": { + "type": [ + "number", + "null" + ], + "description": "The Revision Scan ID of the latest policy scan" + }, + "latestHubbleAnalysisId": { + "type": [ + "number", + "null" + ], + "description": "The Hubble Analysis ID of the latest analysis" + }, + "createdAt": { + "type": "string", + "description": "when the Revision was added to the FOSSA Database" + }, + "updatedAt": { + "type": "string", + "description": "when the Revision was last updated in the FOSSA Database" + }, + "author": { + "type": [ + "string", + "null" + ], + "description": "The author of the Revision" + }, + "link": { + "type": [ + "string", + "null" + ], + "description": "The link associated with the Revision" + }, + "url": { + "type": [ + "string", + "null" + ], + "description": "The url associated with the Revision" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/attribution/email": { + "get": { + "description": "Queue a job to generate and send an email of a revision's attribution report", + "operationId": "getRevisionAttributionEmail", + "tags": [ + "Revisions" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the revision", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "access", + "description": "The public ID", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "preview", + "description": "Whether to preview the report (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "format", + "description": "The format of the report", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "HTML", + "MD", + "PDF", + "CSV", + "TXT", + "SPDX", + "SPDX_JSON", + "CYCLONEDX_JSON", + "CYCLONEDX_XML" + ] + } + }, + { + "name": "includeDeepDependencies", + "description": "Whether to include deep dependencies (default is true)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDirectDependencies", + "description": "Whether to include direct dependencies (default is true)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseList", + "description": "Whether to include the license list (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseScan", + "description": "Whether to include the license scan (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeProjectLicense", + "description": "Whether to include the project license (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyrightList", + "description": "Whether to include the copyright list (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeFileMatches", + "description": "Whether to include the file matches (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeOpenVulnerabilities", + "description": "Whether to include the open vulnerabilities (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeClosedVulnerabilities", + "description": "Whether to include the closed vulnerabilities (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDependencySummary", + "description": "Whether to include the dependency summary (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseHeaders", + "description": "Whether to include the license headers (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includePackageLabels", + "description": "Whether to include the package labels assigned to each dependency (default is false).", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludePackageLabels", + "description": "Exclude dependencies with particular package labels from the report", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "description": "Set of labels to apply to a project" + } + } + } + ], + "responses": { + "200": { + "description": "A JSON representation of the Task in our Database", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "attempt_number": { + "type": "integer", + "description": "The number of attempts" + }, + "id": { + "type": "integer", + "description": "The ID of the task" + }, + "task": { + "type": "string", + "description": "The task to be performed" + }, + "context": { + "type": "object", + "properties": { + "userId": { + "description": "The user's ID", + "type": "integer" + }, + "reportOptions": { + "description": "The report options", + "type": "object", + "properties": { + "download": { + "description": "Whether to download the report", + "required": false, + "type": "boolean" + }, + "createPublicReport": { + "description": "Whether to create a public report", + "required": false, + "type": "boolean" + }, + "email": { + "description": "Whether to email the report", + "required": false, + "type": "boolean" + }, + "includeDeepDependencies": { + "description": "Whether to include deep dependencies", + "required": false, + "type": "boolean" + }, + "includeDirectDependencies": { + "description": "Whether to include direct dependencies", + "required": false, + "type": "boolean" + }, + "includeLicenseList": { + "description": "Whether to include the license list", + "required": false, + "type": "boolean" + }, + "includeLicenseScan": { + "description": "Whether to include the license scan", + "required": false, + "type": "boolean" + }, + "includeProjectLicense": { + "description": "Whether to include the project license", + "required": false, + "type": "boolean" + }, + "includeCopyrightList": { + "description": "Whether to include the copyright list", + "required": false, + "type": "boolean" + }, + "includeFileMatches": { + "description": "Whether to include the file matches", + "required": false, + "type": "boolean" + }, + "includeOpenVulnerabilities": { + "description": "Whether to include the open vulnerabilities", + "required": false, + "type": "boolean" + }, + "includeClosedVulnerabilities": { + "description": "Whether to include the closed vulnerabilities", + "required": false, + "type": "boolean" + }, + "includeDependencySummary": { + "description": "Whether to include the dependency summary", + "required": false, + "type": "boolean" + }, + "includeLicenseHeaders": { + "description": "Whether to include the license headers", + "required": false, + "type": "boolean" + } + } + }, + "locator": { + "description": "The locator", + "type": "string" + } + } + }, + "maxRetries": { + "type": "integer", + "description": "The maximum number of retries" + }, + "scheduledStartTime": { + "type": "string", + "format": "date-time", + "description": "The scheduled start time" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The time the task was last updated" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The time the task was created" + }, + "started": { + "type": "string", + "format": "date-time", + "description": "The time the task was started" + }, + "finished": { + "type": "string", + "format": "date-time", + "description": "The time the task was finished" + }, + "pod": { + "type": "string", + "description": "The pod the task is running on" + }, + "status": { + "type": "string", + "description": "The status of the task" + }, + "jobToken": { + "type": "string", + "description": "The token of the job in the FOSSA Backend" + } + } + }, + "examples": { + "Job": { + "value": { + "status": "CREATED", + "jobToken": "00000000-0000-0000-0000-000000000000", + "context": { + "userId": "0", + "locator": "archive+1/test$1.2.3", + "reportOptions": { + "email": false, + "includeDeepDependencies": false + } + }, + "attempt_number": 1, + "id": 12345, + "task": "GenerateRevisionReport", + "maxRetries": 10, + "scheduledStartTime": "2024-04-23T18:09:59.000Z", + "updatedAt": "2024-04-23T18:09:56.272Z", + "createdAt": "2024-04-23T18:09:56.272Z", + "started": null, + "finished": null, + "pod": null + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": "Not Found" + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/attribution/json": { + "get": { + "description": "Return a JSON report of a revision's attribution", + "operationId": "getRevisionAttributionJSON", + "tags": [ + "Revisions" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "the url-encoded locator of the revision", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "preview", + "description": "Whether to preview the report (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDeepDependencies", + "description": "Whether to include deep dependencies (default is true)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeHashAndVersionData", + "description": "Whether to include hash and version data (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyrightList", + "description": "Whether to include the copyright list (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeFileMatches", + "description": "Whether to include the file matches (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeOpenVulnerabilities", + "description": "Whether to include the open vulnerabilities (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeClosedVulnerabilities", + "description": "Whether to include the closed vulnerabilities (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeNoticeFiles", + "description": "Whether to include the notice files match data (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includePackageLabels", + "description": "Whether to include the package labels assigned to each dependency (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludePackageLabels", + "description": "Exclude dependencies with particular package labels from the report", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "A JSON Report of the Revision's attribution", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "project": { + "type": "object", + "description": "Project information", + "properties": { + "name": { + "type": "string", + "description": "The name of the project" + }, + "revision": { + "type": "string", + "description": "The revision of the project" + } + } + }, + "directDependencies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "package": { + "description": "The package name", + "type": "string" + }, + "source": { + "description": "The source of the package", + "type": "string" + }, + "version": { + "description": "The version of the package", + "type": "string" + }, + "hash": { + "description": "The hash of the package", + "type": "string" + }, + "authors": { + "description": "The authors of the package", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The description of the package", + "type": "string" + }, + "licenses": { + "description": "The licenses of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The name of the license", + "type": "string" + }, + "attribution": { + "description": "The attribution of the license", + "type": "string" + } + } + } + }, + "otherLicenses": { + "description": "The other licenses of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The name of the license", + "type": "string" + }, + "attribution": { + "description": "The attribution of the license", + "type": "string" + } + } + } + }, + "projectUrl": { + "description": "The project URL", + "type": "string" + }, + "dependencyPaths": { + "description": "The dependency paths", + "type": "array", + "items": { + "type": "string" + } + }, + "notes": { + "description": "The notes of the package", + "type": "array", + "items": { + "type": "string" + } + }, + "downloadUrl": { + "required": false, + "description": "The download URL", + "type": "string" + }, + "isGolang": { + "required": false, + "description": "Whether the package is Golang", + "type": "boolean" + }, + "title": { + "description": "The title of the package", + "type": "string" + }, + "noticeFiles": { + "required": false, + "description": "The notice file matches of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "The ID of the notice match", + "type": "integer" + }, + "revisionId": { + "description": "The revision ID of the notice match", + "type": "string" + }, + "contents": { + "description": "The contents of the notice match", + "type": "string" + }, + "copyrights": { + "description": "The copyrights of the notice match", + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "description": "The creation date of the notice match", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The update date of the notice match", + "type": "string", + "format": "date-time" + }, + "corrected": { + "description": "Whether the notice match has been manually corrected", + "type": "boolean" + }, + "ignored": { + "description": "Whether the notice match has been manually ignored", + "type": "boolean" + } + } + } + }, + "packageLabels": { + "required": false, + "description": "All applicable package labels assigned to the package, including globally applied labels, project applied labels, and revision applied labels that match this package in this revision.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "deepDependencies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "package": { + "description": "The package name", + "type": "string" + }, + "source": { + "description": "The source of the package", + "type": "string" + }, + "version": { + "description": "The version of the package", + "type": "string" + }, + "hash": { + "description": "The hash of the package", + "type": "string" + }, + "authors": { + "description": "The authors of the package", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The description of the package", + "type": "string" + }, + "licenses": { + "description": "The licenses of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The name of the license", + "type": "string" + }, + "attribution": { + "description": "The attribution of the license", + "type": "string" + } + } + } + }, + "otherLicenses": { + "description": "The other licenses of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The name of the license", + "type": "string" + }, + "attribution": { + "description": "The attribution of the license", + "type": "string" + } + } + } + }, + "projectUrl": { + "description": "The project URL", + "type": "string" + }, + "dependencyPaths": { + "description": "The dependency paths", + "type": "array", + "items": { + "type": "string" + } + }, + "notes": { + "description": "The notes of the package", + "type": "array", + "items": { + "type": "string" + } + }, + "downloadUrl": { + "required": false, + "description": "The download URL", + "type": "string" + }, + "isGolang": { + "required": false, + "description": "Whether the package is Golang", + "type": "boolean" + }, + "title": { + "description": "The title of the package", + "type": "string" + }, + "noticeFiles": { + "required": false, + "description": "The notice file matches of the package", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "The ID of the notice match", + "type": "integer" + }, + "revisionId": { + "description": "The revision ID of the notice match", + "type": "string" + }, + "contents": { + "description": "The contents of the notice match", + "type": "string" + }, + "copyrights": { + "description": "The copyrights of the notice match", + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "description": "The creation date of the notice match", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The update date of the notice match", + "type": "string", + "format": "date-time" + }, + "corrected": { + "description": "Whether the notice match has been manually corrected", + "type": "boolean" + }, + "ignored": { + "description": "Whether the notice match has been manually ignored", + "type": "boolean" + } + } + } + }, + "packageLabels": { + "required": false, + "description": "All applicable package labels assigned to the package, including globally applied labels, project applied labels, and revision applied labels that match this package in this revision.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "licenses": { + "description": "A record of license names to their text", + "type": "object" + }, + "copyrightsByLicense": { + "description": "A record of license names to their copyrights", + "type": "object" + }, + "noticeFiles": { + "description": "A list of notice file matches", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "The ID of the notice match", + "type": "integer" + }, + "revisionId": { + "description": "The revision ID of the notice match", + "type": "string" + }, + "contents": { + "description": "The contents of the notice match", + "type": "string" + }, + "copyrights": { + "description": "The copyrights of the notice match", + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "description": "The creation date of the notice match", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The update date of the notice match", + "type": "string", + "format": "date-time" + }, + "corrected": { + "description": "Whether the notice match has been manually corrected", + "type": "boolean" + }, + "ignored": { + "description": "Whether the notice match has been manually ignored", + "type": "boolean" + } + } + } + } + } + }, + "examples": { + "Report": { + "value": { + "project": { + "name": "My Project", + "revision": "1.0.0" + }, + "directDependencies": [ + { + "package": "My Package", + "source": "My Source", + "version": "1.0.0", + "hash": "1234", + "authors": [ + "Author 1", + "Author 2" + ], + "description": "My Description", + "licenses": [ + { + "name": "MIT", + "attribution": "Attribution..." + } + ], + "otherLicenses": [ + { + "name": "My Other License", + "attribution": "My Other Attribution" + } + ], + "projectUrl": "http://example.com", + "dependencyPaths": [ + "1" + ], + "notes": [ + "My Note" + ], + "downloadUrl": "http://example.com", + "isGolang": false, + "title": "My Title", + "noticeFiles": [], + "packageLabels": [ + "globally applied label", + "project applied label", + "revision applied label", + "my custom label" + ] + } + ], + "deepDependencies": [ + { + "package": "My Package", + "source": "My Source", + "version": "1.0.0", + "hash": "1234", + "authors": [ + "Author 1", + "Author 2" + ], + "description": "My Description", + "licenses": [ + { + "name": "MIT", + "attribution": "Attribution..." + } + ], + "otherLicenses": [ + { + "name": "My Other License", + "attribution": "My Other Attribution" + } + ], + "projectUrl": "http://example.com", + "dependencyPaths": [ + "1" + ], + "notes": [ + "My Note" + ], + "downloadUrl": "http://example.com", + "isGolang": false, + "title": "My Title", + "noticeFiles": [ + { + "value": { + "id": 1, + "revisionId": "archive+1/NoticeFileTester$1.0", + "path": "vendored/notice-file-tester/NOTICE.txt", + "contents": "Apache Commons Lang\nCopyright 2001-2017 The Apache Software Foundation\n\nThis product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())\n", + "copyrights": [ + "2001-2017 The Apache Software Foundation" + ], + "createdAt": "2024-10-04T15:56:37.579Z", + "updatedAt": "2024-10-04T15:56:37.579Z", + "corrected": false, + "ignored": false + } + } + ], + "packageLabels": [ + "dev-dependency-label" + ] + } + ], + "licenses": { + "MIT": "MIT License" + }, + "copyrightsByLicense": { + "MIT": "Copyright 2020" + }, + "noticeFiles": [ + { + "value": { + "id": 1, + "revisionId": "archive+1/NoticeFileTester$1.0", + "path": "vendored/notice-file-tester/NOTICE.txt", + "contents": "Apache Commons Lang\nCopyright 2001-2017 The Apache Software Foundation\n\nThis product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())\n", + "copyrights": [ + "2001-2017 The Apache Software Foundation" + ], + "createdAt": "2024-10-04T15:56:37.579Z", + "updatedAt": "2024-10-04T15:56:37.579Z", + "corrected": false, + "ignored": false + } + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Revisions found": { + "value": "Not Found" + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/report/remediation-guidance": { + "get": { + "operationId": "fixPlans", + "description": "Returns the Remediation Guidance report for a given revision", + "tags": [ + "Revisions" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "preview", + "description": "Whether to preview the report (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "format", + "description": "What format to return the report in (default is PDF)", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "HTML", + "PDF", + "JSON" + ] + } + }, + { + "name": "bundle", + "description": "Whether to bundle the report with json file and return as a zip (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludeQuickWins", + "description": "Whether to exclude Quick Wins section (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludeHighPriority", + "description": "Whether to exclude High Priority section (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludedLowPriority", + "description": "Whether to exclude Low Priority section (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "excludeOutdatedDependencies", + "description": "Whether to exclude Outdated Dependencies section (default is false)", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/pdf": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/html": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "BadRequest", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "No locator provided!", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "example": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 1006, + "message": "fixPlanReport is not enabled in this organization.", + "name": "FeatureAccessRestrictedError", + "httpStatusCode": 403 + } + } + } + } + } + } + }, + "/revisions/{locator}/original-sbom": { + "get": { + "operationId": "originalSbom", + "description": "Fetch the original user-uploaded SBOM for the given locator, whcih must be the locator for an SBOM project.", + "tags": [ + "Revisions" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "302": { + "description": "Found - a redirect to the original SBOM document", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/sbom-analysis": { + "get": { + "x-internal": true, + "operationId": "sbomAnalysis", + "description": "Fetch the SBOM analysis for the given locator, which must be the locator for an SBOM project.", + "tags": [ + "Revisions" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sbomFile": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "analysis": { + "type": "array", + "items": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error", + "unknown" + ] + }, + "description": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + }, + "requiredFields": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error", + "unknown" + ] + }, + "analysis": { + "type": "array", + "items": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error", + "unknown" + ] + }, + "description": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + } + }, + "dependencyScan": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "analysis": { + "type": "array", + "items": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "description": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "examples": { + "SbomAnalysis": { + "value": { + "sbomFile": { + "status": "success", + "analysis": [ + { + "status": "success", + "description": "File is recognized as an SBOM" + }, + { + "status": "success", + "description": "Components can be identified" + }, + { + "status": "success", + "description": "Relationship between components can be mapped" + } + ] + }, + "requiredFields": { + "status": "error", + "analysis": [ + { + "status": "error", + "description": "Includes component name", + "value": "1/3 components" + }, + { + "status": "success", + "description": "Includes component version", + "value": "3/3 components" + }, + { + "status": "unknown", + "description": "Includes SBOM author", + "value": "unknown" + }, + { + "status": "success", + "description": "Includes creation timestamp", + "value": "2022-11-03T07:10:10.000Z" + }, + { + "status": "success", + "description": "Includes relationship data (SPDX)", + "value": "3/3 components" + }, + { + "status": "success", + "description": "Includes PURL (Package URL)", + "value": "3/3 components" + }, + { + "status": "success", + "description": "Uses minimum version of 2.2 or greater", + "value": "SPDX-2.3" + }, + { + "status": "success", + "description": "Includes supplier", + "value": "3/3 components" + } + ] + }, + "dependencyScan": { + "status": "success", + "analysis": [ + { + "status": "success", + "description": "All dependencies are identified and analyzed", + "value": "1 unknown / 1 failed" + } + ] + } + } + } + } + } + } + }, + "400": { + "description": "BadRequest", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "InvalidSBOMProject": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "The revision is not associated with an SBOM", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/notice-files": { + "get": { + "operationId": "noticeFiles", + "description": "Returns all notice files that were found in the distributed source code", + "tags": [ + "Revisions" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "The ID of the notice match", + "type": "integer" + }, + "revisionId": { + "description": "The revision ID of the notice match", + "type": "string" + }, + "contents": { + "description": "The contents of the notice match", + "type": "string" + }, + "copyrights": { + "description": "The copyrights of the notice match", + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "description": "The creation date of the notice match", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The update date of the notice match", + "type": "string", + "format": "date-time" + }, + "corrected": { + "description": "Whether the notice match has been manually corrected", + "type": "boolean" + }, + "ignored": { + "description": "Whether the notice match has been manually ignored", + "type": "boolean" + } + } + } + }, + "examples": { + "NoticeFile": { + "value": { + "id": 1, + "revisionId": "archive+1/NoticeFileTester$1.0", + "path": "vendored/notice-file-tester/NOTICE.txt", + "contents": "Apache Commons Lang\nCopyright 2001-2017 The Apache Software Foundation\n\nThis product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())\n", + "copyrights": [ + "2001-2017 The Apache Software Foundation" + ], + "createdAt": "2024-10-04T15:56:37.579Z", + "updatedAt": "2024-10-04T15:56:37.579Z", + "corrected": false, + "ignored": false + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/list-dependencies": { + "post": { + "description": "Retrieve dependencies for a given revision using the V1 legacy API format. This is a POST version of the\nGET /api/revisions/:locator/dependencies endpoint that accepts parameters in the request body instead of\nquery parameters. This allows for larger payloads that would exceed URI/header size limits when using query\nparameters (e.g., when filtering by a large list of locators).\n\n**Note**: This endpoint returns the V1 legacy format with streaming JSON array output. For new integrations,\nconsider using the V2 API at GET /v2/revisions/{locator}/dependencies which returns a paginated response with\na cleaner data structure.\n\nThe endpoint returns a streaming JSON array of dependencies with detailed information including the\nDependencyLock, full license objects, issueTargets, and legacy metadata fields.\n", + "operationId": "getRevisionDependenciesPost", + "tags": [ + "Revisions", + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "The URL-encoded locator of the revision", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "example": "custom+1234/my-project$abcd1234" + } + ], + "requestBody": { + "required": false, + "description": "Query parameters for filtering and configuring the dependency response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Maximum number of dependencies to return (min 1, max 10000)", + "minimum": 1, + "maximum": 10000, + "example": 100 + }, + "offset": { + "type": "integer", + "description": "Number of dependencies to skip for pagination", + "minimum": 0, + "example": 0 + }, + "include_ignored": { + "type": "boolean", + "description": "Whether to include ignored dependencies in the response", + "default": false + }, + "includeHashData": { + "type": "boolean", + "description": "Whether to include hash and version data for dependencies", + "default": false + }, + "include_license_text": { + "type": "boolean", + "description": "Whether to include full license text in the license information", + "default": false + }, + "includeLocators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of locators to filter dependencies. Only dependencies matching these locators will be returned", + "example": [ + "npm+lodash$4.17.21", + "maven+com.google.guava:guava$31.1-jre" + ] + } + } + }, + "examples": { + "basic": { + "summary": "Basic request with pagination", + "value": { + "limit": 50, + "offset": 0 + } + }, + "filtered": { + "summary": "Request with locator filtering", + "value": { + "includeLocators": [ + "npm+lodash$4.17.21", + "npm+express$4.18.2" + ], + "include_license_text": true + } + }, + "comprehensive": { + "summary": "Request with all options", + "value": { + "limit": 100, + "offset": 0, + "include_ignored": true, + "includeHashData": true, + "include_license_text": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "A streaming JSON array of dependencies. Each dependency object contains detailed information including\nthe dependency lock, project metadata, licenses, and issues.\n", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Parsed components of the locator", + "properties": { + "fetcher": { + "type": "string", + "nullable": true, + "example": "npm" + }, + "package": { + "type": "string", + "example": "lodash" + }, + "revision": { + "type": "string", + "nullable": true, + "example": "4.17.21" + } + } + }, + "locator": { + "type": "string", + "description": "The full locator string for this dependency", + "example": "npm+lodash$4.17.21" + }, + "projectId": { + "type": "string", + "description": "The package identifier (fetcher+package)", + "example": "npm+lodash" + }, + "resolved": { + "type": "boolean", + "description": "Whether the dependency has been successfully resolved" + }, + "unsupported": { + "type": "boolean", + "description": "Whether the dependency fetcher/type is unsupported" + }, + "latestRevisionScanId": { + "type": "integer", + "nullable": true, + "description": "ID of the latest revision scan (always null for dependencies)" + }, + "DependencyLock": { + "type": "object", + "description": "Information about how this dependency is locked in the project", + "properties": { + "locator": { + "type": "string" + }, + "unresolved_locators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unresolved locators for this dependency" + }, + "depth": { + "type": "integer", + "description": "Depth of this dependency in the dependency tree" + }, + "type": { + "type": "string", + "description": "Type of dependency (deprecated, always \"MEDIATED\")", + "example": "MEDIATED" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for this dependency (deprecated, always empty)" + }, + "is_submodule": { + "type": "boolean", + "description": "Whether this is a submodule (deprecated, always false)" + }, + "root": { + "type": "string", + "description": "The root revision locator" + }, + "origin_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Paths from the root to this dependency" + }, + "manual": { + "type": "boolean", + "description": "Whether this dependency was manually added" + } + } + }, + "project": { + "type": "object", + "description": "Project metadata for the dependency", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "url": { + "type": "string", + "nullable": true + }, + "authors": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "origin_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Paths from the root to this dependency" + }, + "manual": { + "type": "boolean", + "description": "Whether this dependency was manually added" + }, + "unresolved_locators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unresolved locators" + }, + "is_submodule": { + "type": "boolean", + "description": "Whether this is a submodule (deprecated, always false)" + }, + "type": { + "type": "string", + "description": "Type of dependency (deprecated, always \"MEDIATED\")" + }, + "depth": { + "type": "integer", + "description": "Depth in the dependency tree" + }, + "issueTargets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "revisionId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "parentContexts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "issueId": { + "type": "integer" + }, + "projectId": { + "type": "string" + }, + "status": { + "type": "string" + } + } + } + }, + "vulnerability": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + } + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "revisionId": { + "type": "string" + }, + "text": { + "type": "string", + "description": "License text (included if include_license_text is true)" + }, + "licenseId": { + "type": "string" + }, + "licenseGroupId": { + "type": "integer", + "nullable": true + }, + "ignored": { + "type": "boolean" + }, + "copyright": { + "type": "string", + "nullable": true + } + } + } + }, + "ignored": { + "type": "boolean", + "description": "Whether this dependency is ignored" + }, + "downloadUrl": { + "type": "string", + "nullable": true, + "description": "Download URL for the dependency package" + }, + "hash": { + "type": "string", + "description": "Hash of the dependency (included if includeHashData is true)" + }, + "version": { + "type": "string", + "description": "Version of the dependency (included if includeHashData is true)" + }, + "isGolang": { + "type": "boolean", + "description": "Whether this is a Go dependency (included if includeHashData is true)" + }, + "layers": { + "type": "array", + "nullable": true, + "description": "Container layer information (only for container dependencies)", + "items": { + "type": "object", + "properties": { + "layerIndex": { + "type": "integer" + } + } + } + } + } + } + }, + "examples": { + "success": { + "summary": "Example response with two dependencies", + "value": [ + { + "loc": { + "fetcher": "npm", + "package": "lodash", + "revision": "4.17.21" + }, + "locator": "npm+lodash$4.17.21", + "projectId": "npm+lodash", + "resolved": true, + "unsupported": false, + "latestRevisionScanId": null, + "DependencyLock": { + "locator": "npm+lodash$4.17.21", + "unresolved_locators": [], + "depth": 1, + "type": "MEDIATED", + "tags": [], + "is_submodule": false, + "root": "custom+1234/my-project$abcd1234", + "origin_paths": [ + ".", + "node_modules/lodash" + ], + "manual": false + }, + "project": { + "locator": "npm+lodash", + "title": "lodash", + "description": "Lodash modular utilities.", + "url": "https://lodash.com/", + "authors": [ + "John-David Dalton" + ] + }, + "origin_paths": [ + ".", + "node_modules/lodash" + ], + "manual": false, + "unresolved_locators": [], + "is_submodule": false, + "type": "MEDIATED", + "depth": 1, + "issueTargets": [], + "licenses": [ + { + "revisionId": "npm+lodash$4.17.21", + "text": "", + "licenseId": "MIT", + "licenseGroupId": 123, + "ignored": false, + "copyright": "Copyright JS Foundation and other contributors" + } + ], + "ignored": false, + "downloadUrl": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + }, + { + "loc": { + "fetcher": null, + "package": "NULL", + "revision": null + }, + "locator": "NULL", + "projectId": "NULL", + "resolved": false, + "unsupported": false, + "latestRevisionScanId": null, + "DependencyLock": { + "locator": "NULL", + "unresolved_locators": [ + "unknown+dep$1.0.0" + ], + "depth": 1, + "type": "MEDIATED", + "tags": [], + "is_submodule": false, + "root": "custom+1234/my-project$abcd1234", + "origin_paths": [ + "." + ], + "manual": false + }, + "project": { + "locator": "NULL", + "title": "NULL", + "description": "Null placeholder project.", + "url": null, + "authors": [] + }, + "origin_paths": [ + "." + ], + "manual": false, + "unresolved_locators": [ + "unknown+dep$1.0.0" + ], + "is_submodule": false, + "type": "MEDIATED", + "depth": 1, + "issueTargets": [], + "licenses": [], + "ignored": false, + "downloadUrl": null + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Revision not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + }, + "examples": { + "notFound": { + "summary": "Revision not found", + "value": { + "error": "Revision not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/dependencies": { + "get": { + "description": "Retrieve dependencies for a given revision. This endpoint accepts parameters via query string.\nBe sure to chunk large requests to avoid exceeding URI/header size limites. (e.g., when filtering by a large list of locators).\n\nThe endpoint returns a streaming JSON array of dependencies with detailed information including licenses, issues, and metadata.\n", + "operationId": "getRevisionDependencies", + "tags": [ + "Revisions", + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "description": "The URL-encoded locator of the revision", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "example": "custom+1234/my-project$abcd1234" + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of dependencies to return (min 1, max 10000)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 10000, + "example": 100 + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "description": "Number of dependencies to skip for pagination", + "schema": { + "type": "integer", + "minimum": 0, + "example": 0 + } + }, + { + "name": "include_ignored", + "in": "query", + "required": false, + "description": "Whether to include ignored dependencies in the response", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "includeHashData", + "in": "query", + "required": false, + "description": "Whether to include hash and version data for dependencies", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "include_license_text", + "in": "query", + "required": false, + "description": "Whether to include full license text in the license information", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "includeLocators", + "in": "query", + "required": false, + "description": "Array of locators to filter dependencies. Only dependencies matching these locators will be returned.\nNote: For large lists of locators that may exceed URL length limits, use POST /api/revisions/:locator/deps instead.\n", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true, + "example": [ + "npm+lodash$4.17.21", + "maven+com.google.guava:guava$31.1-jre" + ] + } + ], + "responses": { + "200": { + "description": "A streaming JSON array of dependencies. Each dependency object contains detailed information including\nthe dependency lock, project metadata, licenses, and issues.\n", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "loc": { + "type": "object", + "description": "Parsed components of the locator", + "properties": { + "fetcher": { + "type": "string", + "nullable": true, + "example": "npm" + }, + "package": { + "type": "string", + "example": "lodash" + }, + "revision": { + "type": "string", + "nullable": true, + "example": "4.17.21" + } + } + }, + "locator": { + "type": "string", + "description": "The full locator string for this dependency", + "example": "npm+lodash$4.17.21" + }, + "projectId": { + "type": "string", + "description": "The package identifier (fetcher+package)", + "example": "npm+lodash" + }, + "resolved": { + "type": "boolean", + "description": "Whether the dependency has been successfully resolved" + }, + "unsupported": { + "type": "boolean", + "description": "Whether the dependency fetcher/type is unsupported" + }, + "latestRevisionScanId": { + "type": "integer", + "nullable": true, + "description": "ID of the latest revision scan (always null for dependencies)" + }, + "DependencyLock": { + "type": "object", + "description": "Information about how this dependency is locked in the project", + "properties": { + "locator": { + "type": "string" + }, + "unresolved_locators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unresolved locators for this dependency" + }, + "depth": { + "type": "integer", + "description": "Depth of this dependency in the dependency tree" + }, + "type": { + "type": "string", + "description": "Type of dependency (deprecated, always \"MEDIATED\")", + "example": "MEDIATED" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for this dependency (deprecated, always empty)" + }, + "is_submodule": { + "type": "boolean", + "description": "Whether this is a submodule (deprecated, always false)" + }, + "root": { + "type": "string", + "description": "The root revision locator" + }, + "origin_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Paths from the root to this dependency" + }, + "manual": { + "type": "boolean", + "description": "Whether this dependency was manually added" + } + } + }, + "project": { + "type": "object", + "description": "Project metadata for the dependency", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "url": { + "type": "string", + "nullable": true + }, + "authors": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "origin_paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Paths from the root to this dependency" + }, + "manual": { + "type": "boolean", + "description": "Whether this dependency was manually added" + }, + "unresolved_locators": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unresolved locators" + }, + "is_submodule": { + "type": "boolean", + "description": "Whether this is a submodule (deprecated, always false)" + }, + "type": { + "type": "string", + "description": "Type of dependency (deprecated, always \"MEDIATED\")" + }, + "depth": { + "type": "integer", + "description": "Depth in the dependency tree" + }, + "issueTargets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "revisionId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "parentContexts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "issueId": { + "type": "integer" + }, + "projectId": { + "type": "string" + }, + "status": { + "type": "string" + } + } + } + }, + "vulnerability": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + } + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "revisionId": { + "type": "string" + }, + "text": { + "type": "string", + "description": "License text (included if include_license_text is true)" + }, + "licenseId": { + "type": "string" + }, + "licenseGroupId": { + "type": "integer", + "nullable": true + }, + "ignored": { + "type": "boolean" + }, + "copyright": { + "type": "string", + "nullable": true + } + } + } + }, + "ignored": { + "type": "boolean", + "description": "Whether this dependency is ignored" + }, + "downloadUrl": { + "type": "string", + "nullable": true, + "description": "Download URL for the dependency package" + }, + "hash": { + "type": "string", + "description": "Hash of the dependency (included if includeHashData is true)" + }, + "version": { + "type": "string", + "description": "Version of the dependency (included if includeHashData is true)" + }, + "isGolang": { + "type": "boolean", + "description": "Whether this is a Go dependency (included if includeHashData is true)" + }, + "layers": { + "type": "array", + "nullable": true, + "description": "Container layer information (only for container dependencies)", + "items": { + "type": "object", + "properties": { + "layerIndex": { + "type": "integer" + } + } + } + } + } + } + }, + "examples": { + "success": { + "summary": "Example response with two dependencies", + "value": [ + { + "loc": { + "fetcher": "npm", + "package": "lodash", + "revision": "4.17.21" + }, + "locator": "npm+lodash$4.17.21", + "projectId": "npm+lodash", + "resolved": true, + "unsupported": false, + "latestRevisionScanId": null, + "DependencyLock": { + "locator": "npm+lodash$4.17.21", + "unresolved_locators": [], + "depth": 1, + "type": "MEDIATED", + "tags": [], + "is_submodule": false, + "root": "custom+1234/my-project$abcd1234", + "origin_paths": [ + ".", + "node_modules/lodash" + ], + "manual": false + }, + "project": { + "locator": "npm+lodash", + "title": "lodash", + "description": "Lodash modular utilities.", + "url": "https://lodash.com/", + "authors": [ + "John-David Dalton" + ] + }, + "origin_paths": [ + ".", + "node_modules/lodash" + ], + "manual": false, + "unresolved_locators": [], + "is_submodule": false, + "type": "MEDIATED", + "depth": 1, + "issueTargets": [], + "licenses": [ + { + "revisionId": "npm+lodash$4.17.21", + "text": "", + "licenseId": "MIT", + "licenseGroupId": 123, + "ignored": false, + "copyright": "Copyright JS Foundation and other contributors" + } + ], + "ignored": false, + "downloadUrl": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + }, + { + "loc": { + "fetcher": null, + "package": "NULL", + "revision": null + }, + "locator": "NULL", + "projectId": "NULL", + "resolved": false, + "unsupported": false, + "latestRevisionScanId": null, + "DependencyLock": { + "locator": "NULL", + "unresolved_locators": [ + "unknown+dep$1.0.0" + ], + "depth": 1, + "type": "MEDIATED", + "tags": [], + "is_submodule": false, + "root": "custom+1234/my-project$abcd1234", + "origin_paths": [ + "." + ], + "manual": false + }, + "project": { + "locator": "NULL", + "title": "NULL", + "description": "Null placeholder project.", + "url": null, + "authors": [] + }, + "origin_paths": [ + "." + ], + "manual": false, + "unresolved_locators": [ + "unknown+dep$1.0.0" + ], + "is_submodule": false, + "type": "MEDIATED", + "depth": 1, + "issueTargets": [], + "licenses": [], + "ignored": false, + "downloadUrl": null + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "404": { + "description": "Revision not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + }, + "examples": { + "notFound": { + "summary": "Revision not found", + "value": { + "error": "Revision not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/builds": { + "get": { + "operationId": "getBuilds", + "description": "Retrieves a list of builds.", + "tags": [ + "Builds" + ], + "parameters": [ + { + "name": "locator", + "description": "The revision locator to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "description": "The project locator to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "startDate", + "description": "The start date to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endDate", + "description": "The end date to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "pageSize", + "description": "The number of builds to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "page", + "description": "The page number to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "description": "The sort order(s) to apply to the builds", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "cliVersionId", + "createdAt", + "id", + "locator", + "ownerId", + "taskId", + "updatedAt" + ] + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Build list", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "The ID for the build", + "type": "integer" + }, + "locator": { + "description": "The revision locator for the build", + "type": "string" + }, + "ownerId": { + "description": "The ID of the user who owns the build", + "type": [ + "integer", + "null" + ] + }, + "error": { + "description": "The error message for the build", + "type": [ + "string", + "null" + ] + }, + "warnings": { + "description": "The warning messages for the build", + "type": "array", + "items": { + "type": "string" + } + }, + "provided": { + "description": "Is the build from a CLI upload", + "type": "boolean" + }, + "taskId": { + "description": "The ID of the task for the build", + "type": [ + "integer", + "null" + ] + }, + "createdAt": { + "description": "The date and time the build was created", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The date and time the build was last updated", + "type": "string", + "format": "date-time" + }, + "cliVersionId": { + "description": "The ID of the CLI version for the build", + "type": "integer" + }, + "revision": { + "description": "The revision for the build", + "type": "object", + "properties": { + "locator": { + "description": "The revision locator for the build", + "type": "string" + }, + "projectId": { + "description": "The project locator of the project for the build", + "type": "integer" + }, + "message": { + "description": "The message for the revision", + "type": "string" + } + } + }, + "task": { + "description": "The task for the build", + "type": "object", + "properties": { + "status": { + "description": "The status of the task", + "type": "string", + "enum": [ + "CREATED", + "ASSIGNED", + "RUNNING", + "SUCCEEDED", + "FAILED" + ] + }, + "started": { + "description": "The date and time the task was started", + "type": "string", + "format": "date-time" + }, + "finished": { + "description": "The date and time the task was finished", + "type": "string", + "format": "date-time" + }, + "createdAt": { + "description": "The date and time the task was created", + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "description": "The date and time the task was last updated", + "type": "string", + "format": "date-time" + }, + "attempt_number": { + "description": "The number of attempts for the task", + "type": "integer" + }, + "maxRetries": { + "description": "The maximum number of retries for the task", + "type": "integer" + } + } + } + } + } + }, + "examples": { + "build": { + "value": [ + { + "id": 1, + "locator": "git+gitproject$1.2.3", + "ownerId": 1, + "error": "error", + "warnings": [ + "warning 1", + "warning 2" + ], + "provided": true, + "createdAt": "2021-01-01T00:00:00Z", + "updatedAt": "2021-01-01T00:00:00Z", + "taskId": 1, + "cliVersionId": 1, + "revision": { + "locator": "git+gitproject$1.2.3", + "projectId": "git+gitproject", + "message": "message" + }, + "task": { + "status": "SUCCEEDED", + "started": "2021-01-01T00:00:00Z", + "finished": "2021-01-01T00:00:00Z", + "createdAt": "2021-01-01T00:00:00Z", + "updatedAt": "2021-01-01T00:00:00Z", + "attempt_number": 1, + "maxRetries": 1 + } + }, + { + "id": 2, + "locator": "git+gitproject$1.2.3", + "ownerId": 1, + "error": "error", + "warnings": [ + "warning 1", + "warning 2" + ], + "provided": true, + "createdAt": "2021-01-01T00:00:00Z", + "updatedAt": "2021-01-01T00:00:00Z", + "taskId": 2, + "cliVersionId": 1, + "revision": { + "locator": "git+gitproject$1.2.3", + "projectId": "git+gitproject", + "message": "message" + }, + "task": { + "status": "SUCCEEDED", + "started": "2021-01-01T00:00:00Z", + "finished": "2021-01-01T00:00:00Z", + "createdAt": "2021-01-01T00:00:00Z", + "updatedAt": "2021-01-01T00:00:00Z", + "attempt_number": 1, + "maxRetries": 1 + } + } + ] + } + } + } + } + }, + "400": { + "description": "Malformed Payload", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "invalid query parameters": { + "value": { + "uuid": "12345678-1234-1234-1234-123456789012", + "code": 400, + "message": "'locator' or 'projectId' must be passed in to this endpoint.", + "name": "MalformedPayloadError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/counts/builds": { + "get": { + "operationId": "getBuildsCount", + "description": "Retrieves a count of builds.", + "tags": [ + "Builds" + ], + "parameters": [ + { + "name": "locator", + "description": "The revision locator to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "description": "The project locator to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "startDate", + "description": "The start date to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endDate", + "description": "The end date to filter builds to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "pageSize", + "description": "The number of builds to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "page", + "description": "The page number to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "description": "The sort order(s) to apply to the builds", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "cliVersionId", + "createdAt", + "id", + "locator", + "ownerId", + "taskId", + "updatedAt" + ] + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Build counts", + "content": { + "application/json": { + "schema": { + "type": "number" + }, + "examples": { + "build": { + "value": 4 + } + } + } + } + }, + "400": { + "description": "Malformed Payload", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "invalid query parameters": { + "value": { + "uuid": "12345678-1234-1234-1234-123456789012", + "code": 400, + "message": "'locator' or 'projectId' must be passed in to this endpoint.", + "name": "MalformedPayloadError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/users": { + "get": { + "operationId": "getAllUsers", + "description": "This endpoint is deprecated. Please use the paginated /v2/users/ endpoint instead.", + "deprecated": true, + "tags": [ + "Users" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "count", + "schema": { + "type": "integer" + }, + "description": "The numbers of users being returned" + }, + { + "in": "query", + "name": "page", + "schema": { + "type": "integer" + }, + "description": "The page number of users being returned" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The user's unique identifier" + }, + "username": { + "type": [ + "string", + "null" + ], + "description": "The user's username" + }, + "email": { + "type": [ + "string", + "null" + ], + "description": "The user's email address" + }, + "email_verified": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user's email address has been verified" + }, + "demo": { + "type": "boolean", + "description": "Whether the user is a demo user" + }, + "super": { + "type": "boolean", + "description": "Whether the user is a super user" + }, + "joined": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user joined the organization" + }, + "last_visit": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user last visited the organization" + }, + "terms_agreed": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user agreed to the organization's terms" + }, + "full_name": { + "type": [ + "string", + "null" + ], + "description": "The user's full name" + }, + "phone": { + "type": [ + "string", + "null" + ], + "description": "The user's phone number" + }, + "role": { + "type": [ + "string", + "null" + ], + "description": "The user's role in the organization" + }, + "organizationId": { + "type": "integer", + "description": "The organization the user belongs to" + }, + "sso_only": { + "type": "boolean", + "description": "Whether the user is SSO only" + }, + "enabled": { + "type": "boolean", + "description": "Whether the user is enabled" + }, + "has_set_password": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user has set a password" + }, + "install_admin": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user is an install admin" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was last updated" + }, + "userRole": { + "type": "object", + "properties": { + "roleId": { + "type": "integer", + "description": "The user's Organization role ID" + }, + "role": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization the role belongs to" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "scope": { + "type": "string", + "description": "The role's scope" + } + } + } + } + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The token's unique identifier" + }, + "name": { + "type": "string", + "description": "The token's name" + }, + "isDisabled": { + "type": "boolean" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was last updated" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was created" + }, + "meta": { + "type": "object", + "properties": { + "pushOnly": { + "type": "boolean", + "description": "Whether the token is push only" + } + }, + "defaultPolicyId": { + "type": "integer", + "description": "The token's default licensing policy ID" + }, + "defaultSecurityPolicyId": { + "type": "integer", + "description": "The token's default security policy ID" + }, + "defaultQualityPolicyId": { + "type": "integer", + "description": "The token's default quality policy ID" + } + } + } + } + }, + "teamUsers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleId": { + "type": "integer", + "description": "The user's role ID" + }, + "team": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + } + } + } + } + } + }, + "organization": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "title": { + "type": "string", + "description": "The organization's title" + }, + "access_level": { + "type": "string", + "description": "The organization's access level" + } + } + }, + "github": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's GitHub username" + }, + "email": { + "type": "string", + "description": "The user's GitHub email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's GitHub avatar URL" + } + } + }, + "bitbucketCloud": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's Bitbucket Cloud username" + }, + "email": { + "type": "string", + "description": "The user's Bitbucket Cloud email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's Bitbucket Cloud avatar URL" + } + } + } + } + } + }, + "examples": { + "user": { + "value": [ + { + "id": 1, + "username": "user1", + "email": "email@email.com", + "email_verified": true, + "demo": false, + "super": false, + "joined": "2020-01-01", + "last_visit": "2020-01-01", + "terms_agreed": "2020-01-01", + "full_name": "User One", + "phone": "123-456-7890", + "role": "User", + "organizationId": 1, + "sso_only": false, + "enabled": true, + "has_set_password": true, + "install_admin": false, + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "userRole": { + "roleId": 1, + "role": { + "id": 1, + "organizationId": 1, + "isCustom": false, + "scope": "organization", + "name": "User" + } + }, + "tokens": [], + "github": { + "name": "user1", + "email": null, + "avatar_url": "https://avatars.githubusercontent.com/u/3067666?v=4" + }, + "organization": { + "id": 1, + "title": "Organization One", + "access_level": "premium" + } + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/users/{id}": { + "get": { + "operationId": "getUser", + "description": "Get user by ID", + "tags": [ + "Users" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "description": "The user's unique identifier", + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The user's unique identifier" + }, + "username": { + "type": [ + "string", + "null" + ], + "description": "The user's username" + }, + "email": { + "type": [ + "string", + "null" + ], + "description": "The user's email address" + }, + "email_verified": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user's email address has been verified" + }, + "demo": { + "type": "boolean", + "description": "Whether the user is a demo user" + }, + "super": { + "type": "boolean", + "description": "Whether the user is a super user" + }, + "joined": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user joined the organization" + }, + "last_visit": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user last visited the organization" + }, + "terms_agreed": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user agreed to the organization's terms" + }, + "full_name": { + "type": [ + "string", + "null" + ], + "description": "The user's full name" + }, + "phone": { + "type": [ + "string", + "null" + ], + "description": "The user's phone number" + }, + "role": { + "type": [ + "string", + "null" + ], + "description": "The user's role in the organization" + }, + "organizationId": { + "type": "integer", + "description": "The organization the user belongs to" + }, + "sso_only": { + "type": "boolean", + "description": "Whether the user is SSO only" + }, + "enabled": { + "type": "boolean", + "description": "Whether the user is enabled" + }, + "has_set_password": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user has set a password" + }, + "install_admin": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user is an install admin" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was last updated" + }, + "userRole": { + "type": "object", + "properties": { + "roleId": { + "type": "integer", + "description": "The user's Organization role ID" + }, + "role": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization the role belongs to" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "scope": { + "type": "string", + "description": "The role's scope" + } + } + } + } + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The token's unique identifier" + }, + "name": { + "type": "string", + "description": "The token's name" + }, + "isDisabled": { + "type": "boolean" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was last updated" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was created" + }, + "meta": { + "type": "object", + "properties": { + "pushOnly": { + "type": "boolean", + "description": "Whether the token is push only" + } + }, + "defaultPolicyId": { + "type": "integer", + "description": "The token's default licensing policy ID" + }, + "defaultSecurityPolicyId": { + "type": "integer", + "description": "The token's default security policy ID" + }, + "defaultQualityPolicyId": { + "type": "integer", + "description": "The token's default quality policy ID" + } + } + } + } + }, + "teamUsers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleId": { + "type": "integer", + "description": "The user's role ID" + }, + "team": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The team's unique identifier" + }, + "name": { + "type": "string", + "description": "The team's name" + } + } + } + } + } + }, + "organization": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "title": { + "type": "string", + "description": "The organization's title" + }, + "access_level": { + "type": "string", + "description": "The organization's access level" + } + } + }, + "github": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's GitHub username" + }, + "email": { + "type": "string", + "description": "The user's GitHub email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's GitHub avatar URL" + } + } + }, + "bitbucketCloud": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's Bitbucket Cloud username" + }, + "email": { + "type": "string", + "description": "The user's Bitbucket Cloud email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's Bitbucket Cloud avatar URL" + } + } + } + } + } + }, + "examples": { + "user": { + "value": { + "id": 1, + "username": "user1", + "email": "email@email.com", + "email_verified": true, + "demo": false, + "super": false, + "joined": "2020-01-01", + "last_visit": "2020-01-01", + "terms_agreed": "2020-01-01", + "full_name": "User One", + "phone": "123-456-7890", + "role": "User", + "organizationId": 1, + "sso_only": false, + "enabled": true, + "has_set_password": true, + "install_admin": false, + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2020-01-01T00:00:00Z", + "userRole": { + "roleId": 1, + "role": { + "id": 1, + "organizationId": 1, + "isCustom": false, + "scope": "organization", + "name": "User" + } + }, + "tokens": [], + "github": { + "name": "user1", + "email": null, + "avatar_url": "https://avatars.githubusercontent.com/u/3067666?v=4" + }, + "organization": { + "id": 1, + "title": "Organization One", + "access_level": "premium" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/users/service-accounts": { + "post": { + "operationId": "createServiceAccount", + "description": "Create a new service account with specified roles and optional API tokens", + "tags": [ + "Users" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "username" + ], + "properties": { + "username": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "The username for the service account", + "example": "api-service-prod" + }, + "email": { + "type": "string", + "format": "email", + "maxLength": 255, + "description": "Optional email address for the service account", + "example": "api-service@company.com" + }, + "fullName": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Optional full name/description for the service account", + "example": "Production API Service Account" + }, + "orgRoleId": { + "type": "integer", + "minimum": 1, + "description": "ID of the organization role to assign to the service account. At least one of orgRoleId or team must be provided.", + "example": 3 + }, + "team": { + "type": "object", + "description": "Team assignment for the service account. At least one of orgRoleId or team must be provided.", + "required": [ + "id", + "roleId" + ], + "properties": { + "id": { + "type": "integer", + "minimum": 1, + "description": "ID of the team to assign the service account to", + "example": 5 + }, + "roleId": { + "type": "integer", + "minimum": 1, + "description": "ID of the team role to assign", + "example": 6 + } + } + }, + "hasPushOnlyApiToken": { + "type": "boolean", + "default": false, + "description": "Whether to create a push-only API token for the service account", + "example": true + }, + "hasFullApiToken": { + "type": "boolean", + "default": false, + "description": "Whether to create a full access API token for the service account", + "example": false + } + }, + "description": "Create a new service account. You must provide at least one of the following:\n- `orgRoleId`: Assigns an organization-level role\n- `team`: Assigns a team-level role with specified team ID and role ID\n- Both `orgRoleId` and `team`: Assigns both organization and team roles\n\nNote that if assigning the service account to a team, the account making the API request must be part of that team and\nbe assigning the service account a permission that is equal to or less powerful than their own role on that team.\n" + }, + "examples": { + "createOrgServiceAccount": { + "summary": "Create service account with organization role", + "value": { + "username": "production-api-service", + "email": "prod-api@company.com", + "fullName": "Production API Service Account", + "orgRoleId": 3, + "hasPushOnlyApiToken": false, + "hasFullApiToken": false + } + }, + "createTeamServiceAccount": { + "summary": "Create service account with team role", + "value": { + "username": "team-ci-service", + "fullName": "Team CI Service Account", + "team": { + "id": 5, + "roleId": 6 + }, + "hasPushOnlyApiToken": true, + "hasFullApiToken": false + } + }, + "createWithTokens": { + "summary": "Create service account with API tokens", + "value": { + "username": "automation-service", + "email": "automation@company.com", + "fullName": "Automation Service Account", + "orgRoleId": 2, + "hasPushOnlyApiToken": true, + "hasFullApiToken": true + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Service account created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id", + "username" + ], + "properties": { + "id": { + "type": "integer", + "description": "The user id of the service account", + "example": 12345 + }, + "username": { + "type": "string", + "description": "The username of the service account", + "example": "api-service-prod" + }, + "email": { + "type": [ + "string", + "null" + ], + "description": "The email address of the service account (if provided)", + "example": "api-service@company.com" + }, + "full_name": { + "type": [ + "string", + "null" + ], + "description": "The full name/description of the service account (if provided)", + "example": "Production API Service Account" + }, + "fullApiToken": { + "type": "string", + "description": "The full access API token (only present if hasFullApiToken was true)", + "example": "1234567890abcdef1234567890abcdef12345678" + }, + "pushOnlyApiToken": { + "type": "string", + "description": "The push-only API token (only present if hasPushOnlyApiToken was true)", + "example": "abcdef1234567890abcdef1234567890abcdef12" + } + } + }, + "examples": { + "serviceAccountWithTokens": { + "value": { + "id": 12345, + "username": "automation-service", + "email": "automation@company.com", + "full_name": "Automation Service Account", + "fullApiToken": "fossa-api-key-1234567890abcdef1234567890abcdef12345678", + "pushOnlyApiToken": "fossa-push-key-abcdef1234567890abcdef1234567890abcdef12" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Team not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "teamNotFound": { + "value": { + "message": "Team not found." + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/users": { + "get": { + "operationId": "getAllUsersV2", + "description": "Get a paginated list of users in your organization", + "tags": [ + "Users" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "description": "Page number (1-indexed, defaults to 1)", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "description": "Number of items per page (defaults to 10, max 50)", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Search term to filter users by username, email, or full name (max 255)", + "schema": { + "type": "string", + "maxLength": 255 + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort order for results. Use format `field_asc` or `field_desc`. Supported fields: username, full_name, email, created_at, last_visit.", + "schema": { + "type": "string", + "enum": [ + "username_asc", + "username_desc", + "full_name_asc", + "full_name_desc", + "email_asc", + "email_desc", + "created_at_asc", + "created_at_desc", + "last_visit_asc", + "last_visit_desc" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of users", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The user's unique identifier" + }, + "username": { + "type": [ + "string", + "null" + ], + "description": "The user's username" + }, + "email": { + "type": [ + "string", + "null" + ], + "description": "The user's email address" + }, + "email_verified": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user's email address has been verified" + }, + "demo": { + "type": "boolean", + "description": "Whether the user is a demo user" + }, + "super": { + "type": "boolean", + "description": "Whether the user is a super user" + }, + "joined": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user joined the organization" + }, + "last_visit": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user last visited the organization" + }, + "terms_agreed": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "The date the user agreed to the organization's terms" + }, + "full_name": { + "type": [ + "string", + "null" + ], + "description": "The user's full name" + }, + "phone": { + "type": [ + "string", + "null" + ], + "description": "The user's phone number" + }, + "role": { + "type": [ + "string", + "null" + ], + "description": "The user's role in the organization" + }, + "organizationId": { + "type": "integer", + "description": "The organization the user belongs to" + }, + "sso_only": { + "type": "boolean", + "description": "Whether the user is SSO only" + }, + "enabled": { + "type": "boolean", + "description": "Whether the user is enabled" + }, + "has_set_password": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user has set a password" + }, + "install_admin": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the user is an install admin" + }, + "isServiceAccount": { + "type": "boolean", + "description": "Whether the user is a service account" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the user was last updated" + }, + "userRole": { + "type": "object", + "nullable": true, + "properties": { + "roleId": { + "type": "integer", + "description": "The user's Organization role ID" + }, + "role": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The role's unique identifier" + }, + "organizationId": { + "type": "integer", + "description": "The organization the role belongs to" + }, + "isCustom": { + "type": "boolean", + "description": "Whether the role is custom" + }, + "name": { + "type": "string", + "description": "The role's name" + }, + "scope": { + "type": "string", + "description": "The role's scope" + } + } + } + } + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The token's unique identifier" + }, + "name": { + "type": "string", + "description": "The token's name" + }, + "isDisabled": { + "type": "boolean" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was last updated" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date the token was created" + }, + "meta": { + "type": "object", + "nullable": true, + "properties": { + "pushOnly": { + "type": "boolean", + "description": "Whether the token is push only" + }, + "defaultPolicyId": { + "type": "integer", + "description": "The token's default licensing policy ID" + }, + "defaultSecurityPolicyId": { + "type": "integer", + "description": "The token's default security policy ID" + }, + "defaultQualityPolicyId": { + "type": "integer", + "description": "The token's default quality policy ID" + } + } + } + } + } + }, + "teamsCount": { + "type": "integer", + "description": "Number of teams the user belongs to" + }, + "organization": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The organization's unique identifier" + }, + "title": { + "type": "string", + "description": "The organization's title" + }, + "access_level": { + "type": "string", + "description": "The organization's access level" + } + } + }, + "github": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's GitHub username" + }, + "email": { + "type": "string", + "description": "The user's GitHub email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's GitHub avatar URL" + } + } + }, + "bitbucketCloud": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user's Bitbucket Cloud username" + }, + "email": { + "type": "string", + "description": "The user's Bitbucket Cloud email address" + }, + "avatar_url": { + "type": "string", + "description": "The user's Bitbucket Cloud avatar URL" + } + } + } + } + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page" + }, + "page": { + "type": "integer", + "description": "Current page number (1-indexed)" + }, + "totalCount": { + "type": "integer", + "description": "Total number of users" + } + }, + "required": [ + "results", + "pageSize", + "page", + "totalCount" + ] + }, + "examples": { + "users": { + "value": { + "results": [ + { + "id": 1, + "username": "jdoe", + "email": "jdoe@example.com", + "email_verified": true, + "demo": false, + "super": false, + "joined": "2020-01-01T00:00:00Z", + "last_visit": "2024-01-01T00:00:00Z", + "full_name": "John Doe", + "phone": null, + "role": null, + "organizationId": 1, + "sso_only": false, + "enabled": true, + "has_set_password": true, + "install_admin": false, + "isServiceAccount": false, + "createdAt": "2020-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z", + "userRole": { + "roleId": 1, + "role": { + "id": 1, + "organizationId": 1, + "isCustom": false, + "name": "Admin", + "scope": "organization" + } + }, + "teamsCount": 2 + } + ], + "pageSize": 10, + "page": 1, + "totalCount": 1 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/revisions/{locator}/dependencies": { + "get": { + "operationId": "getProjectDependencies", + "description": "Get the dependencies for a given project revision", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "locators[]", + "description": "Filter dependencies by locators (exact match)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "title", + "description": "Filter dependencies by title", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status[]", + "description": "Filter dependencies by status", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "analyzing", + "analyzed", + "failed", + "unknown" + ] + } + } + }, + { + "name": "depth[]", + "description": "Filter dependencies by depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "transitive" + ] + } + } + }, + { + "name": "layerDepth[]", + "description": "Filter dependencies by depth (for container projects)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "base", + "other" + ] + } + } + }, + { + "name": "hasIssues[]", + "description": "Filter dependencies by the presence of issues", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "hasIssues", + "hasLicensingIssues", + "hasQualityIssues", + "hasVulnIssues", + "noIssues" + ] + } + } + }, + { + "name": "licenses[]", + "description": "Filter dependencies by licenses", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "fetchers[]", + "description": "Filter dependencies by package manager", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "showIgnored", + "description": "Includes ignored dependencies", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "confidence[]", + "description": "Filter dependencies by confidence", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "High", + "Medium", + "Low", + "Unknown" + ] + } + } + }, + { + "name": "sources[]", + "description": "Filter dependencies by source type (managed or vendored). Only supported on project scope.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed", + "vendored" + ] + } + } + }, + { + "name": "rootProjects[]", + "description": "Filter release group dependencies by root projects", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "packageLabels[]", + "description": "Filter dependencies by package label IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "vendoredPath", + "description": "Filter to vendored dependencies found under this path prefix. Only supported on project scope.", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "includeResolutionNotes", + "description": "Include resolution notes in issue data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseText", + "description": "Include full license text in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyright", + "description": "Include copyright information in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeMatches", + "description": "Include license match details in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDownloadUrl", + "description": "Include download URL in package data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 25, + "maximum": 100, + "default": 50 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "isManual": { + "type": "boolean" + }, + "isIgnored": { + "type": "boolean" + }, + "isUnknown": { + "type": "boolean" + }, + "isSnippetConversion": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "declaredLicenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "depth": { + "type": "integer" + }, + "originPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "unsupported": { + "type": "boolean" + }, + "analyzing": { + "type": "boolean" + } + } + }, + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + }, + "license": { + "type": "string" + }, + "cvssScore": { + "type": "number" + } + } + } + }, + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + }, + "layerDepth": { + "type": "number" + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendoredPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + } + } + }, + "count": { + "type": "integer" + } + } + }, + "examples": { + "dependencies": { + "value": { + "total": 2, + "dependencies": [ + { + "locator": "npm+foo$1.2.3", + "title": "foo", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + "MIT", + "Apache" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT", + "Apache" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 1, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 123, + "type": "policy_conflict", + "status": "active", + "license": "Apache", + "analysisSnippetId": 123, + "vulnId": null, + "cvssScore": null, + "projectId": "custom+123/myproject$1.2.3" + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main" + } + ], + "cpes": [ + "cpe:2.3:a:foo:foo:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [ + "src/installed/foo" + ] + }, + { + "locator": "git+bar$1.2.3", + "title": "bar", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + null + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 2, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 321, + "type": "vulnerability", + "status": "active", + "cvssScore": 5.4 + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main" + } + ], + "cpes": [ + "cpe:2.3:a:bar:bar:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [], + "version": "1.2.3" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/revisions/{locator}/dependencies/{dependencyRevisionLocator}": { + "get": { + "operationId": "getProjectDependency", + "description": "Get a single dependency by locator for a given project revision", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The locator of the project revision" + }, + { + "name": "dependencyRevisionLocator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The locator of the dependency to retrieve" + }, + { + "name": "includeResolutionNotes", + "description": "Include resolution notes in issue data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseText", + "description": "Include full license text in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyright", + "description": "Include copyright information in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeMatches", + "description": "Include license match details in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDownloadUrl", + "description": "Include download URL in package data", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependency": { + "type": "object", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "isManual": { + "type": "boolean" + }, + "isIgnored": { + "type": "boolean" + }, + "isUnknown": { + "type": "boolean" + }, + "isSnippetConversion": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "declaredLicenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "depth": { + "type": "integer" + }, + "originPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "unsupported": { + "type": "boolean" + }, + "analyzing": { + "type": "boolean" + } + } + }, + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + }, + "license": { + "type": "string" + }, + "cvssScore": { + "type": "number" + } + } + } + }, + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + }, + "layerDepth": { + "type": "number" + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendoredPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + } + } + } + }, + "examples": { + "dependency": { + "value": { + "dependency": { + "locator": "npm+foo$1.2.3", + "title": "foo", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT", + "Apache" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 1, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 123, + "type": "policy_conflict", + "status": "active", + "license": "Apache" + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main", + "conclusions": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + } + } + ], + "cpes": [ + "cpe:2.3:a:foo:foo:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [ + "src/installed/foo" + ], + "version": "1.2.3" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request": { + "summary": "Missing required parameters", + "value": { + "error": "Dependency revision locator is required." + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Project Revision Not Found": { + "summary": "Project revision does not exist", + "value": { + "error": "This project revision does not exist" + } + }, + "Dependency Not Found": { + "summary": "Dependency revision not found", + "value": { + "error": "Dependency revision not found" + } + } + } + } + } + } + } + } + }, + "/v2/revisions/{locator}/dependencies/package-managers": { + "get": { + "operationId": "getProjectDependencyPackageManagers", + "description": "Get the package managers present in the dependencies of a given project revision", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "examples": { + "packageManagers": { + "value": { + "packageManagers": [ + "npm", + "mvn" + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/revisions/{locator}/dependencies/count": { + "get": { + "operationId": "getProjectDependencyCount", + "description": "Get the total count of dependencies for a given project revision", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The locator of the project revision" + }, + { + "name": "sources[]", + "description": "Filter dependencies by source type (managed or vendored). Only supported on project scope.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed", + "vendored" + ] + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "The total number of dependencies for this project revision" + } + } + }, + "example": { + "count": 42 + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/dependencies/{locator}": { + "get": { + "operationId": "getGlobalDependency", + "description": "Get a single dependency by locator in the global scope", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The locator of the dependency to retrieve" + }, + { + "name": "includeResolutionNotes", + "description": "Include resolution notes in issue data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseText", + "description": "Include full license text in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyright", + "description": "Include copyright information in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeMatches", + "description": "Include license match details in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDownloadUrl", + "description": "Include download URL in package data", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependency": { + "type": "object", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "isManual": { + "type": "boolean" + }, + "isIgnored": { + "type": "boolean" + }, + "isUnknown": { + "type": "boolean" + }, + "isSnippetConversion": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "declaredLicenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "depth": { + "type": "integer" + }, + "originPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "unsupported": { + "type": "boolean" + }, + "analyzing": { + "type": "boolean" + } + } + }, + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + }, + "license": { + "type": "string" + }, + "cvssScore": { + "type": "number" + } + } + } + }, + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + }, + "layerDepth": { + "type": "number" + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendoredPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + } + } + } + }, + "examples": { + "dependency": { + "value": { + "dependency": { + "locator": "npm+foo$1.2.3", + "title": "foo", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT", + "Apache" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 1, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 123, + "type": "policy_conflict", + "status": "active", + "license": "Apache" + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main", + "conclusions": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + } + } + ], + "cpes": [ + "cpe:2.3:a:foo:foo:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [ + "src/installed/foo" + ], + "version": "1.2.3" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Dependency Not Found": { + "summary": "Dependency with locator not found or no permission", + "value": { + "error": "Dependency with locator npm+nonexistent$1.0.0 not found or you do not have permission to view it" + } + } + } + } + } + } + } + } + }, + "/v2/dependencies/custom-licenses": { + "get": { + "operationId": "getCustomLicenses", + "description": "Get custom licenses (dependency licenses that have been manually corrected) within the organization.\nThis endpoint returns paginated results of custom licenses that have been created through project corrections.\nThe results can be optionally filtered to a specific project using the `projectLocator` query parameter.\n", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectLocator", + "in": "query", + "required": false, + "description": "Optional project locator to filter results to custom licenses used within a specific project.\nIf not provided, returns custom licenses across all projects the user has access to.\n", + "schema": { + "type": "string" + }, + "example": "custom+1234/my-project" + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved custom licenses", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "description": "A custom license represents a dependency license that has been manually corrected or overridden\nthrough project corrections. This includes custom license text, copyright information, and metadata.\n", + "properties": { + "dependencyProjectLocator": { + "type": "string", + "description": "The locator of the dependency project that this custom license applies to", + "example": "npm+lodash" + }, + "dependencyRevisionLocator": { + "type": "string", + "description": "The specific revision locator of the dependency", + "example": "npm+lodash$4.17.21" + }, + "projectLocator": { + "type": "string", + "description": "The locator of the user project that contains this dependency", + "example": "custom+1234/my-project" + }, + "projectRevision": { + "type": "string", + "description": "The revision locator of the user project", + "example": "custom+1234/my-project$789xyz456" + }, + "title": { + "type": "string", + "description": "The title/name of the dependency project", + "example": "My Custom Dependency" + }, + "description": { + "type": "string", + "description": "Description of the dependency project", + "example": "A useful library for data processing" + }, + "url": { + "type": "string", + "description": "URL for the dependency project", + "example": "https://github.com/example/dependency" + }, + "licenseTitle": { + "type": "string", + "description": "The custom license title/name", + "example": "Custom Commercial License" + }, + "licenseId": { + "type": "string", + "description": "The license identifier, always 'custom-license' for custom licenses", + "enum": [ + "custom-license" + ], + "example": "custom-license" + }, + "copyright": { + "type": "string", + "description": "Copyright notice for this license", + "example": "Copyright (c) 2024 Example Corp. All rights reserved." + }, + "text": { + "type": "string", + "description": "The full text of the license", + "example": "This is a proprietary license.\n\nPermission is granted to use this software under the following conditions...\n" + }, + "correctedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the license correction was created", + "example": "2024-03-15T10:30:00.000Z" + } + }, + "required": [ + "dependencyProjectLocator", + "dependencyRevisionLocator", + "projectLocator", + "projectRevision", + "title", + "description", + "url", + "licenseTitle", + "licenseId", + "copyright", + "text", + "correctedAt" + ], + "additionalProperties": false + }, + "description": "Array of custom license objects" + }, + "totalCount": { + "type": "integer", + "description": "Total number of custom licenses available (across all pages)", + "minimum": 0 + }, + "page": { + "type": "integer", + "description": "Current page number", + "minimum": 1 + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page", + "minimum": 1, + "maximum": 1000 + } + }, + "required": [ + "results", + "totalCount", + "page", + "pageSize" + ] + }, + "examples": { + "customLicenses": { + "summary": "Custom licenses response example", + "description": "Example response showing custom licenses with pagination information", + "value": { + "results": [ + { + "dependencyProjectLocator": "custom+1234/lodash", + "dependencyRevisionLocator": "custom+1234/lodash$v4.17.21", + "projectLocator": "custom+1234/my-web-app", + "projectRevision": "custom+1234/my-web-app$main-branch-abc123", + "title": "Lodash Utility Library", + "description": "A modern JavaScript utility library delivering modularity, performance & extras.", + "url": "https://lodash.com", + "licenseTitle": "Custom Commercial License for Lodash", + "licenseId": "custom-license", + "copyright": "Copyright (c) JS Foundation and other contributors", + "text": "Custom Commercial License\n\nThis is a custom license agreement for the use of Lodash\nin commercial applications.\n\nPermission is hereby granted to use this software under\nthe following terms and conditions...\n", + "correctedAt": "2024-03-15T10:30:00.000Z" + }, + { + "dependencyProjectLocator": "custom+1234/react", + "dependencyRevisionLocator": "custom+1234/react$18.2.0", + "projectLocator": "custom+1234/my-web-app", + "projectRevision": "custom+1234/my-web-app$main-branch-abc123", + "title": "React", + "description": "A JavaScript library for building user interfaces", + "url": "https://reactjs.org", + "licenseTitle": "Modified MIT License", + "licenseId": "custom-license", + "copyright": "Copyright (c) Facebook, Inc. and its affiliates.", + "text": "MIT License (Modified)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software with additional restrictions...\n", + "correctedAt": "2024-03-14T14:22:15.000Z" + } + ], + "totalCount": 25, + "page": 1, + "pageSize": 10 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Invalid request", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No team Access": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "You are not permitted to view this team.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Project not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "projectNotFound": { + "summary": "Project not found", + "value": { + "error": "Project not found for locator: custom+1234/invalid-project" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/{projectGroupId}/releases/{projectGroupReleaseId}/dependencies": { + "get": { + "operationId": "getReleaseGroupDependencies", + "description": "Get the dependencies for a given release group", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectGroupId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "locators[]", + "description": "Filter dependencies by locators (exact match)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "title", + "description": "Filter dependencies by title", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status[]", + "description": "Filter dependencies by status", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "analyzing", + "analyzed", + "failed", + "unknown" + ] + } + } + }, + { + "name": "depth[]", + "description": "Filter dependencies by depth", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "direct", + "transitive" + ] + } + } + }, + { + "name": "layerDepth[]", + "description": "Filter dependencies by depth (for container projects)", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "base", + "other" + ] + } + } + }, + { + "name": "hasIssues[]", + "description": "Filter dependencies by the presence of issues", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "hasIssues", + "hasLicensingIssues", + "hasQualityIssues", + "hasVulnIssues", + "noIssues" + ] + } + } + }, + { + "name": "licenses[]", + "description": "Filter dependencies by licenses", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "fetchers[]", + "description": "Filter dependencies by package manager", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "showIgnored", + "description": "Includes ignored dependencies", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "confidence[]", + "description": "Filter dependencies by confidence", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "High", + "Medium", + "Low", + "Unknown" + ] + } + } + }, + { + "name": "sources[]", + "description": "Filter dependencies by source type (managed or vendored). Only supported on project scope.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed", + "vendored" + ] + } + } + }, + { + "name": "rootProjects[]", + "description": "Filter release group dependencies by root projects", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "packageLabels[]", + "description": "Filter dependencies by package label IDs", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "vendoredPath", + "description": "Filter to vendored dependencies found under this path prefix. Only supported on project scope.", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "includeResolutionNotes", + "description": "Include resolution notes in issue data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseText", + "description": "Include full license text in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyright", + "description": "Include copyright information in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeMatches", + "description": "Include license match details in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDownloadUrl", + "description": "Include download URL in package data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "count", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 25, + "maximum": 100, + "default": 50 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependencies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "isManual": { + "type": "boolean" + }, + "isIgnored": { + "type": "boolean" + }, + "isUnknown": { + "type": "boolean" + }, + "isSnippetConversion": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "declaredLicenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "depth": { + "type": "integer" + }, + "originPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "unsupported": { + "type": "boolean" + }, + "analyzing": { + "type": "boolean" + } + } + }, + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + }, + "license": { + "type": "string" + }, + "cvssScore": { + "type": "number" + } + } + } + }, + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + }, + "layerDepth": { + "type": "number" + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendoredPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + } + } + }, + "count": { + "type": "integer" + } + } + }, + "examples": { + "dependencies": { + "value": { + "total": 2, + "dependencies": [ + { + "locator": "npm+foo$1.2.3", + "title": "foo", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + "MIT", + "Apache" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT", + "Apache" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 1, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 123, + "type": "policy_conflict", + "status": "active", + "license": "Apache", + "analysisSnippetId": 123, + "vulnId": null, + "cvssScore": null, + "projectId": "custom+123/myproject$1.2.3" + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main" + } + ], + "cpes": [ + "cpe:2.3:a:foo:foo:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [ + "src/installed/foo" + ] + }, + { + "locator": "git+bar$1.2.3", + "title": "bar", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + null + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 2, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 321, + "type": "vulnerability", + "status": "active", + "cvssScore": 5.4 + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main" + } + ], + "cpes": [ + "cpe:2.3:a:bar:bar:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [], + "version": "1.2.3" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/{projectGroupId}/releases/{projectGroupReleaseId}/dependencies/{dependencyRevisionLocator}": { + "get": { + "operationId": "getReleaseGroupDependency", + "description": "Get a single dependency by locator for a given release group", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectGroupId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + }, + "description": "The ID of the release group" + }, + { + "name": "projectGroupReleaseId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + }, + "description": "The ID of the release" + }, + { + "name": "dependencyRevisionLocator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The locator of the dependency to retrieve" + }, + { + "name": "includeResolutionNotes", + "description": "Include resolution notes in issue data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeLicenseText", + "description": "Include full license text in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeCopyright", + "description": "Include copyright information in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeMatches", + "description": "Include license match details in license data", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "includeDownloadUrl", + "description": "Include download URL in package data", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dependency": { + "type": "object", + "properties": { + "locator": { + "type": "string" + }, + "title": { + "type": "string" + }, + "isManual": { + "type": "boolean" + }, + "isIgnored": { + "type": "boolean" + }, + "isUnknown": { + "type": "boolean" + }, + "isSnippetConversion": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + }, + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "declaredLicenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "depth": { + "type": "integer" + }, + "originPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "unsupported": { + "type": "boolean" + }, + "analyzing": { + "type": "boolean" + } + } + }, + "issues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "ignored" + ] + }, + "license": { + "type": "string" + }, + "cvssScore": { + "type": "number" + } + } + } + }, + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + }, + "layerDepth": { + "type": "number" + }, + "cpes": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendoredPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "version": { + "type": "string" + } + } + } + } + }, + "examples": { + "dependency": { + "value": { + "dependency": { + "locator": "npm+foo$1.2.3", + "title": "foo", + "isManual": false, + "isIgnored": false, + "isUnknown": false, + "isSnippetConversion": false, + "concludedLicenses": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + }, + "licenses": [ + "MIT", + "Apache" + ], + "declaredLicenses": [ + "MIT" + ], + "depth": 1, + "originPaths": [ + "package.json" + ], + "status": { + "error": "", + "resolved": true, + "unsupported": false, + "analyzing": false + }, + "issues": [ + { + "id": 123, + "type": "policy_conflict", + "status": "active", + "license": "Apache" + } + ], + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main", + "conclusions": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + } + } + ], + "cpes": [ + "cpe:2.3:a:foo:foo:1.2.3:*:*:*:*:*:*" + ], + "vendoredPaths": [ + "src/installed/foo" + ], + "version": "1.2.3" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request": { + "summary": "Invalid parameters", + "value": { + "error": "Invalid projectGroupId: NaN" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Not Found": { + "summary": "Release does not exist", + "value": { + "error": "This release does not exist" + } + }, + "Dependency Not Found": { + "summary": "Dependency revision not found", + "value": { + "error": "Dependency revision not found" + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/{projectGroupId}/releases/{projectGroupReleaseId}/dependencies/package-managers": { + "get": { + "operationId": "getReleaseGroupDependencyPackageManagers", + "description": "Get the package managers present in the dependencies of a given release group", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectGroupId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packageManagers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "examples": { + "packageManagers": { + "value": { + "packageManagers": [ + "npm", + "mvn" + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/{projectGroupId}/releases/{projectGroupReleaseId}/dependencies/count": { + "get": { + "operationId": "getReleaseGroupDependencyCount", + "description": "Get the total count of dependencies for a given release group", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectGroupId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + }, + "description": "The ID of the release group" + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "sources[]", + "description": "Filter dependencies by source type (managed or vendored). Only supported on project scope.", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "managed", + "vendored" + ] + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "The total number of dependencies for this release group" + } + } + }, + "example": { + "count": 42 + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v2/release-groups/{projectGroupId}/releases/{projectGroupReleaseId}/root-projects": { + "get": { + "operationId": "getReleaseGroupDependencyRootProjects", + "description": "Get the root projects present in the dependencies of a given release group", + "tags": [ + "Dependencies" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "projectGroupId", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + }, + { + "name": "projectGroupReleaseId", + "description": "The ID of the release", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "rootProjects": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "branch": { + "type": "string" + }, + "conclusions": { + "type": "object", + "properties": { + "scoped": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "lastEditedBy": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "base": { + "type": "object", + "properties": { + "licenses": { + "type": "array", + "items": { + "type": "string" + } + }, + "justification": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "examples": { + "rootProjects": { + "value": { + "rootProjects": [ + { + "title": "myproject", + "revision": "custom+123/myproject$1.2.3", + "branch": "main", + "conclusions": { + "scoped": { + "licenses": [ + "Apache-2.0", + "ISC" + ], + "lastEditedBy": "user@fossa.com", + "updatedAt": "2025-01-01T00:00:00Z" + }, + "base": { + "licenses": [ + "MIT" + ], + "justification": "Concluded by FOSSA" + } + } + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/vulns/cve-list": { + "get": { + "operationId": "getCveList", + "description": "Search for CVEs by query string and return top matching distinct CVE identifiers with their details", + "tags": [ + "Vulnerabilities" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "query", + "required": true, + "in": "query", + "description": "Search string to find matching CVE identifiers", + "schema": { + "type": "string" + }, + "example": "CVE-2021" + } + ], + "responses": { + "200": { + "description": "OK - Returns a list of matching CVEs with details", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "cve": { + "type": "string", + "description": "CVE identifier (e.g., CVE-2021-44228)", + "pattern": "^CVE-\\d{4}-\\d{4,}$", + "example": "CVE-2021-44228" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Detailed description of the vulnerability", + "example": "Apache Log4j2 2.0-beta9 through 2.15.0 JNDI features used in configuration do not protect against attacker controlled LDAP endpoints." + } + }, + "required": [ + "cve" + ] + } + }, + "example": [ + { + "cve": "CVE-2021-44228", + "description": "Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints." + }, + { + "cve": "CVE-2021-45046", + "description": "It was found that the fix to address CVE-2021-44228 in Apache Log4j 2.15.0 was incomplete in certain non-default configurations." + } + ] + } + } + }, + "400": { + "description": "Bad Request - Search string not provided", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing API token", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden - Security features not enabled for organization", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/vulns/{vulnId}/revisions/{revisionId}/remediation-guidance": { + "get": { + "operationId": "getRemediationGuidance", + "description": "Get remediation guidance for a given vuln id and revision id", + "tags": [ + "Vulnerabilities" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "vulnId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "revisionId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "partialFix": { + "type": "string" + }, + "partialFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + }, + "completeFix": { + "type": "string" + }, + "completeFixDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/general": { + "get": { + "operationId": "getOrganizationGeneralSettings", + "description": "Get general settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "label": { + "type": "string" + }, + "projectCount": { + "type": "integer" + } + } + } + }, + "title": { + "type": "string" + }, + "email": { + "type": "string" + }, + "defaultRoleId": { + "type": "integer" + }, + "dependencySignatures": { + "type": "string" + }, + "disableNonCustomTeamUserRoles": { + "type": "boolean" + } + } + }, + "examples": { + "GeneralOrganizationSettings": { + "value": { + "labels": [ + { + "label": "critical", + "id": 1, + "projectCount": 10 + } + ], + "title": "title", + "email": "test@fossa.com", + "defaultRoleId": 1, + "dependencySignatures": "1,2,3", + "disableNonCustomTeamUserRoles": false + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationGeneralSettings", + "description": "Update general settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, + "title": { + "type": "string" + }, + "email": { + "type": "string" + }, + "defaultRoleId": { + "type": "integer" + }, + "dependencySignatures": { + "type": "string" + }, + "disableNonCustomTeamUserRoles": { + "type": "boolean" + } + } + }, + "examples": { + "EditingGeneralOrganizationSettings": { + "value": { + "labels": [ + "critical", + "low" + ], + "title": "title", + "email": "test@fossa.com", + "defaultRoleId": 1, + "dependencySignatures": "1,2,3", + "disableNonCustomTeamUserRoles": false + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Settings Payload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/privacy": { + "get": { + "operationId": "getOrganizationProjectPrivacySettings", + "description": "Get project privacy settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultProjectPrivacy": { + "description": "the default privacy setting for new projects", + "type": "string", + "enum": [ + "public", + "private" + ], + "nullable": true + } + } + }, + "example": { + "defaultProjectPrivacy": "private" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationProjectPrivacySettings", + "description": "Update project privacy settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultProjectPrivacy": { + "description": "the default privacy setting for new projects", + "type": "string", + "enum": [ + "public", + "private" + ], + "nullable": true + } + } + }, + "example": { + "defaultProjectPrivacy": "private" + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationProjectPrivacySettings", + "description": "Propagate project privacy settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "defaultProjectPrivacy" + ] + } + }, + "example": [ + "defaultProjectPrivacy" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/github-status-checks": { + "get": { + "operationId": "getOrganizationGithubStatusCheckSettings", + "description": "Get github status check settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "projectDefaultAutomatedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultProvidedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultIntegrationhookFailState": { + "type": "string", + "enum": [ + "ERROR", + "SUCCESS" + ] + } + } + }, + "example": { + "projectDefaultAutomatedIntegrationhookTimeout": 150, + "projectDefaultProvidedIntegrationhookTimeout": 80, + "projectDefaultIntegrationhookFailState": "ERROR" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationGithubStatusCheckSettings", + "description": "Update github status check settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "projectDefaultAutomatedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultProvidedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultIntegrationhookFailState": { + "type": "string", + "enum": [ + "ERROR", + "SUCCESS" + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationGithubStatusCheckSettings", + "description": "Propagate github status check settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "projectDefaultAutomatedIntegrationhookTimeout", + "projectDefaultProvidedIntegrationhookTimeout", + "projectDefaultIntegrationhookFailState" + ] + } + }, + "example": [ + "projectDefaultAutomatedIntegrationhookTimeout", + "projectDefaultProvidedIntegrationhookTimeout", + "projectDefaultIntegrationhookFailState" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/issues/licensing": { + "get": { + "operationId": "getOrganizationLicensingIssueSettings", + "description": "Get licensing issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultPolicyId": { + "type": "integer" + }, + "projectDefaultLicensingIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultLicensingStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterLicensing": { + "type": "integer" + }, + "projectDefaultSnippetLicensingIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet licensing issue scanning by default for projects in the organization" + } + } + }, + "example": { + "defaultPolicyId": 1, + "projectDefaultLicensingIssueScanningEnabled": true, + "projectDefaultLicensingStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterLicensing": 1, + "projectDefaultSnippetLicensingIssueScanningEnabled": true + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationLicensingIssueSettings", + "description": "Update licensing issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultPolicyId": { + "type": "integer" + }, + "projectDefaultLicensingIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultLicensingStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterLicensing": { + "type": "integer" + }, + "projectDefaultSnippetLicensingIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet licensing issue scanning by default for projects in the organization" + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Settings Payload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationLicensingIssueSettings", + "description": "Propagate licensing issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "defaultPolicyId", + "projectDefaultLicensingIssueScanningEnabled", + "projectDefaultLicensingStatusCheckEnabled", + "projectDefaultStatusCheckFilterLicensing", + "projectDefaultSnippetLicensingIssueScanningEnabled" + ] + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/issues/security": { + "get": { + "operationId": "getOrganizationSecurityIssueSettings", + "description": "Get security issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultSecurityPolicyId": { + "type": "integer" + }, + "projectDefaultSecurityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultSecurityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterVulnerability": { + "type": "integer" + }, + "projectDefaultSnippetSecurityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet security issue scanning by default for projects in the organization" + } + } + }, + "examples": { + "SecurityIssueSettings": { + "value": { + "defaultSecurityPolicyId": 1, + "projectDefaultSecurityIssueScanningEnabled": true, + "projectDefaultSecurityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterVulnerability": 4, + "projectDefaultSnippetSecurityIssueScanningEnabled": false + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationSecurityIssueSettings", + "description": "Update security issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultSecurityPolicyId": { + "type": "integer" + }, + "projectDefaultSecurityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultSecurityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterVulnerability": { + "type": "integer" + }, + "projectDefaultSnippetSecurityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet security issue scanning by default for projects in the organization" + } + } + }, + "examples": { + "SecurityIssueSettings": { + "value": { + "defaultSecurityPolicyId": 1, + "projectDefaultSecurityIssueScanningEnabled": true, + "projectDefaultSecurityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterVulnerability": 4, + "projectDefaultSnippetSecurityIssueScanningEnabled": false + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Settings Payload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationSecurityIssueSettings", + "description": "Propagate security issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "defaultSecurityPolicyId", + "projectDefaultSecurityIssueScanningEnabled", + "projectDefaultSecurityStatusCheckEnabled", + "projectDefaultStatusCheckFilterVulnerability", + "projectDefaultSnippetSecurityIssueScanningEnabled" + ] + } + }, + "example": [ + "defaultSecurityPolicyId", + "projectDefaultSecurityIssueScanningEnabled", + "projectDefaultSecurityStatusCheckEnabled", + "projectDefaultStatusCheckFilterVulnerability", + "projectDefaultSnippetSecurityIssueScanningEnabled" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/issues/quality": { + "get": { + "operationId": "getOrganizationQualityIssueSettings", + "description": "Get quality issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultQualityPolicyId": { + "type": "integer" + }, + "projectDefaultQualityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultQualityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterQuality": { + "type": "integer" + } + } + }, + "examples": { + "QualityIssueSettings": { + "value": { + "defaultQualityPolicyId": 1, + "projectDefaultQualityIssueScanningEnabled": true, + "projectDefaultQualityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterQuality": 1 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationQualityIssueSettings", + "description": "Update quality issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaultQualityPolicyId": { + "type": "integer" + }, + "projectDefaultQualityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultQualityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterQuality": { + "type": "integer" + } + } + }, + "examples": { + "QualityIssueSettings": { + "value": { + "defaultQualityPolicyId": 1, + "projectDefaultQualityIssueScanningEnabled": true, + "projectDefaultQualityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterQuality": 1 + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Settings Payload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationQualityIssueSettings", + "description": "Propagate quality issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "defaultQualityPolicyId", + "projectDefaultQualityIssueScanningEnabled", + "projectDefaultQualityStatusCheckEnabled", + "projectDefaultStatusCheckFilterQuality" + ] + } + }, + "example": [ + "defaultQualityPolicyId", + "projectDefaultQualityIssueScanningEnabled", + "projectDefaultQualityStatusCheckEnabled", + "projectDefaultStatusCheckFilterQuality" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/issues/container": { + "get": { + "operationId": "getOrganizationContainerIssueSettings", + "description": "Get container issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "projectDefaultExcludeBaseLayerIssuesLicensing": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesSecurity": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesQuality": { + "type": "boolean" + } + } + }, + "examples": { + "ContainerIssueSettings": { + "value": { + "projectDefaultExcludeBaseLayerIssuesLicensing": true, + "projectDefaultExcludeBaseLayerIssuesSecurity": true, + "projectDefaultExcludeBaseLayerIssuesQuality": true + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationContainerIssueSettings", + "description": "Update container issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "projectDefaultExcludeBaseLayerIssuesLicensing": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesSecurity": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesQuality": { + "type": "boolean" + } + } + }, + "examples": { + "ContainerIssueSettings": { + "value": { + "projectDefaultExcludeBaseLayerIssuesLicensing": true, + "projectDefaultExcludeBaseLayerIssuesSecurity": true, + "projectDefaultExcludeBaseLayerIssuesQuality": true + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationContainerIssueSettings", + "description": "Propagate container issue settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "projectDefaultExcludeBaseLayerIssuesLicensing", + "projectDefaultExcludeBaseLayerIssuesSecurity", + "projectDefaultExcludeBaseLayerIssuesQuality" + ] + } + }, + "example": [ + "projectDefaultExcludeBaseLayerIssuesLicensing", + "projectDefaultExcludeBaseLayerIssuesSecurity", + "projectDefaultExcludeBaseLayerIssuesQuality" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/v1/share-requests": { + "get": { + "operationId": "getShareRequests", + "description": "Get a list of share requests created by the caller's organization. This lists all SBOM revisions that have been shared with other organizations.", + "tags": [ + "SBOM" + ], + "parameters": [ + { + "name": "projectLocator", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filter share requests by project locator" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A list of share requests created by the caller's organization.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "shareRequests": { + "type": "array", + "items": { + "type": "object", + "properties": { + "originRevisionId": { + "type": "string", + "description": "The ID of the revision that was shared" + }, + "originProjectLocator": { + "type": "string", + "description": "The locator of the project that was shared" + }, + "projectTitle": { + "type": "string", + "description": "The title of the project that was shared" + }, + "sharedOrganizationId": { + "type": "integer", + "format": "int64", + "description": "The ID of the shared organization record" + }, + "sharedAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp when the share was created" + }, + "receivingOrganizationName": { + "type": "string", + "description": "The name of the organization that received the share" + } + } + } + } + } + }, + "examples": { + "With share requests": { + "value": { + "shareRequests": [ + { + "originRevisionId": "sbom+123/project-name$1.0.0", + "originProjectLocator": "sbom+123/project-name", + "projectTitle": "SBOM Project", + "sharedOrganizationId": 456, + "sharedAt": "2024-05-15T10:30:00Z", + "receivingOrganizationName": "Partner Organization" + } + ] + } + }, + "No share requests": { + "value": { + "shareRequests": [] + } + }, + "Filtered by project": { + "value": { + "shareRequests": [ + { + "originRevisionId": "sbom+123/project-name$1.0.0", + "originProjectLocator": "sbom+123/project-name", + "projectTitle": "SBOM Project", + "sharedOrganizationId": 456, + "sharedAt": "2024-05-15T10:30:00Z", + "receivingOrganizationName": "Partner Organization" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Feature flag not enabled": { + "value": { + "message": "sbomSharing is not enabled in this organization." + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createShareRequest", + "description": "Create a new share request for an SBOM revision. This endpoint queues a job to process the share request and returns a task reference.", + "tags": [ + "SBOM" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "revisionId", + "sharedOrganizationId" + ], + "properties": { + "revisionId": { + "type": "string", + "description": "The locator for the revision to share" + }, + "sharedOrganizationId": { + "type": "integer", + "format": "int64", + "description": "The ID of the shared organization record" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "201": { + "description": "The share request was created successfully and a job was queued to process it.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "task": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifier for the task type (e.g., \"ProjectRevisionShare\")" + }, + "jobToken": { + "type": "string", + "description": "Token used to track the share job" + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid request body": { + "value": { + "message": "Invalid request body: revisionId is required" + } + }, + "Invalid revision type": { + "value": { + "message": "Only revisions from SBOM projects can be shared." + } + }, + "Invalid team": { + "value": { + "message": "You do not have permission to share with this team." + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Feature flag not enabled": { + "value": { + "message": "sbomSharing is not enabled in this organization." + } + }, + "No permission": { + "value": { + "message": "You do not have permission to share this revision." + } + }, + "Not authorized": { + "value": { + "message": "You are not authorized to share with this organization." + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision with ID sbom+999/nonexistent$1.0.0 not found or you don't have permission to access it." + } + }, + "Shared organization not found": { + "value": { + "message": "Shared organization with ID 9999 not found." + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/v1/shared-organizations": { + "get": { + "operationId": "getLinkedOrganizations", + "description": "Get a list of organizations that are linked to the caller's organization for SBOM sharing. This endpoint returns both organizations the caller can share with and organizations that have shared with the caller.", + "tags": [ + "SBOM" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A list of organizations linked to the caller's organization for SBOM sharing.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "organizationsToShareWith": { + "type": "array", + "items": { + "type": "object", + "properties": { + "sharedOrganizationId": { + "type": "integer", + "format": "int64", + "description": "The ID of the shared organization record" + }, + "originOrganizationName": { + "type": "string", + "description": "The name of the origin organization" + }, + "receivingOrganizationName": { + "type": "string", + "description": "The name of the receiving organization" + } + } + } + }, + "organizationsThatHaveSharedWithMe": { + "type": "array", + "items": { + "type": "object", + "properties": { + "sharedOrganizationId": { + "type": "integer", + "format": "int64", + "description": "The ID of the shared organization record" + }, + "originOrganizationName": { + "type": "string", + "description": "The name of the origin organization" + }, + "receivingOrganizationName": { + "type": "string", + "description": "The name of the receiving organization" + } + } + } + } + } + }, + "examples": { + "With linked organizations": { + "value": { + "organizationsToShareWith": [ + { + "sharedOrganizationId": 123, + "originOrganizationName": "My Organization", + "receivingOrganizationName": "Partner Company" + } + ], + "organizationsThatHaveSharedWithMe": [ + { + "sharedOrganizationId": 456, + "originOrganizationName": "Source Company", + "receivingOrganizationName": "My Organization" + } + ] + } + }, + "No linked organizations": { + "value": { + "organizationsToShareWith": [], + "organizationsThatHaveSharedWithMe": [] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Feature flag not enabled": { + "value": { + "message": "sbomSharing is not enabled in this organization." + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/{revisionLocator}/{dependencyLocator}/components": { + "get": { + "operationId": "getRevisionDependencyComponents", + "description": "Get Binary Decomposition Components for a Dependency of a Binary Decomposition Revision", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + }, + { + "name": "dependencyLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Dependency revision" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A list of components associated with a dependency of a Binary Decomposition project revision.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "componentId": { + "type": "string", + "description": "The ID of the component" + }, + "filePath": { + "type": "string", + "description": "The filepath of the component" + }, + "matchCount": { + "type": "number", + "description": "The number of matches" + } + } + } + }, + "page": { + "type": "number", + "description": "pagination page" + }, + "pageSize": { + "type": "number", + "description": "pagination page page size" + }, + "totalCount": { + "type": "number", + "description": "total count of components" + } + } + }, + "examples": { + "Example response": { + "value": { + "results": [ + { + "componentId": "1a515e48-b718-4c54-8943-10f40e44e1c7", + "filePath": "NUGUauto-v2.2.8-signed.apk/classes2.dex", + "matchCount": 11 + }, + { + "componentId": "e74da06d-f019-42c5-abe7-cc6aab81c5b2", + "filePath": "NUGUauto-v2.2.8-signed.apk/classes2.dex", + "matchCount": 6 + }, + { + "componentId": "f604dfed-8d7a-4dc0-8351-fdad99ba77a6", + "filePath": "NUGUauto-v2.2.8-signed.apk/utils.dex", + "matchCount": 13 + } + ], + "page": 1, + "pageSize": 10, + "totalCount": 3 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator and dependency locator are required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/{revisionLocator}/{componentId}/matches": { + "get": { + "operationId": "getRevisionComponentMatches", + "description": "Get Matches for a Binary Decomposition Component for a Revision", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + }, + { + "name": "componentId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "The ID of the component" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A list of matches associated with a component of a Binary Decomposition project revision.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "matchString": { + "type": "string", + "description": "The string the match occurred on" + }, + "count": { + "type": "number", + "description": "The number occurences of match string" + } + } + } + }, + "page": { + "type": "number", + "description": "pagination page" + }, + "pageSize": { + "type": "number", + "description": "pagination page page size" + }, + "totalCount": { + "type": "number", + "description": "total count of component matches" + } + } + }, + "examples": { + "Example response": { + "value": { + "results": [ + { + "matchString": "conversion from %s to Decimal is not supported", + "count": 11 + }, + { + "matchString": "coefficient must be a tuple of digits", + "count": 9 + }, + { + "matchString": "This operation is unaffected by context and is quiet: no flags are changed", + "count": 9 + }, + { + "matchString": "argument must be a Decimal", + "count": 5 + }, + { + "matchString": "IEEE_Invalid_operation", + "count": 5 + } + ], + "page": 1, + "pageSize": 5, + "totalCount": 132 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator and componentId are required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/revision/{revisionLocator}/components/count": { + "get": { + "operationId": "getRevisionComponentsCount", + "description": "Get number of Binary Decomposition Components for a Revision with an associated Binary Decomposition Scan", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Count of Binary Decomposition Components for a Revision.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "number", + "description": "Count of Binary Decomposition Components for a revision" + } + } + }, + "examples": { + "Example response": { + "value": { + "count": 42 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + }, + "Associated scan not found": { + "value": { + "message": "Scan not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/revision/{revisionLocator}/components/paths": { + "get": { + "operationId": "getRevisionComponentsPaths", + "description": "Get Binary Decomposition Components by path for a Revision with an associated Binary Decomposition Scan", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + }, + { + "name": "path", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Path to find components at" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Paths and counts of Binary Decomposition Components for a Revision.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "A directory node with component count", + "properties": { + "type": { + "type": "string", + "enum": [ + "directory" + ], + "description": "Type of component path node (directory or file)" + }, + "name": { + "type": "string", + "description": "Name of directory" + }, + "path": { + "type": "string", + "description": "Path to directory" + }, + "count": { + "type": "number", + "nullable": true, + "description": "Count of component matches in directory" + } + } + }, + { + "type": "object", + "description": "A file node with component revision and root project revision", + "properties": { + "type": { + "type": "string", + "enum": [ + "file" + ], + "description": "Type of component path node (directory or file)" + }, + "name": { + "type": "string", + "description": "Name of file" + }, + "path": { + "type": "string", + "description": "Path to file" + }, + "revisionId": { + "type": "string", + "description": "Dependency revision matched in file" + }, + "componentId": { + "type": "string", + "description": "Component Id for dependency and file" + }, + "packageName": { + "type": "string", + "description": "Package name of Dependency matched in file" + }, + "version": { + "type": "string", + "description": "Version of Dependency matched in file" + }, + "rootProjectRevisionLocator": { + "type": "string", + "description": "Revision of root Binary Decomposition project" + } + } + } + ] + } + } + } + }, + "examples": { + "Example response": { + "value": { + "paths": [ + { + "type": "file", + "name": "aes.py", + "path": "main/crypto/aes.py", + "componentId": "4d24c136-30ea-43b9-a3ef-6613f3eed03b", + "revisionId": "csbinary+python/aes$1.2.3", + "packageName": "aes", + "version": "1.2.3", + "rootProjectRevisionLocator": "binary+uploadedBinaryProject$1746028908005" + }, + { + "type": "directory", + "name": "utils", + "path": "main/crypto/utils", + "count": 10 + }, + { + "type": "directory", + "name": "auth", + "path": "main/crypto/auth", + "count": 4 + }, + { + "type": "file", + "name": "diffie-hellman.py", + "path": "main/crypto/diffie-hellman.py", + "componentId": "4d24c136-30ea-43b9-a3ef-6613f3eed03b", + "revisionId": "csbinary+python/mayo$4.4vbeta", + "packageName": "mayo", + "version": "4.4vbeta", + "rootProjectRevisionLocator": "binary+uploadedBinaryProject$1746028908005" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + }, + "Associated scan not found": { + "value": { + "message": "Scan not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/{revisionLocator}/dependency-confidence": { + "get": { + "operationId": "getRevisionDependencyConfidence", + "description": "Get Confidence values for the Binary Component Dependencies of a Binary Decomposition Revision", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A mapping from Binary Component dependencies to Confidence values.", + "content": { + "application/json": { + "schema": { + "type": "object", + "confidences": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + } + } + }, + "examples": { + "Example response": { + "value": { + "confidences": { + "cs-binary+example/example$1.2.3": "High", + "cs-binary+sample/sample$2.3.4": "Medium", + "cs-binary+dummy/dummy$3.4.5": "Low", + "cs-binary+fake/fake$4.5.6": "Unknown" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + }, + "Scan not found": { + "value": { + "message": "Scan not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/{revisionLocator}/dependency-confidence/{dependencyLocator}": { + "get": { + "operationId": "getSingleRevisionDependencyConfidence", + "description": "Get Confidence value for a single Binary Component Dependency of a Binary Decomposition Revision", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "revisionLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Binary Decomposition project revision" + }, + { + "name": "dependencyLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Dependency revision" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A mapping from a single Binary Component dependency to its Confidence value.", + "content": { + "application/json": { + "schema": { + "type": "object", + "confidences": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + } + } + }, + "examples": { + "Example response": { + "value": { + "confidences": { + "cs-binary+example/example$1.2.3": "High" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Revision locator is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Revision not found": { + "value": { + "message": "Revision not found" + } + }, + "Scan not found": { + "value": { + "message": "Scan not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/release-group/{releaseGroupId}/release/{releaseId}/components/count": { + "get": { + "operationId": "getReleaseComponentsCount", + "description": "Get number of Binary Decomposition Components for a Release of a Release Group with at least one associated Binary Decomposition Scan", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "releaseGroupId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release group id" + }, + { + "name": "releaseId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release id" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Count of Binary Decomposition Components for a Release of a Release Group.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "number", + "description": "Count of Binary Decomposition Components for a Release of a Release Group" + } + } + }, + "examples": { + "Example response": { + "value": { + "count": 42 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Release group ID and release ID are required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group not found": { + "value": { + "message": "Release group not found" + } + }, + "Release not found": { + "value": { + "message": "Release not found" + } + }, + "No associated scans found": { + "value": { + "message": "No binary scans found for release" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/release-group/{releaseGroupId}/release/{releaseId}/components/paths": { + "get": { + "operationId": "getReleaseComponentsPaths", + "description": "Get Binary Decomposition Components by path for a a Release of a Release Group with at least one associated Binary Decomposition Scan", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "releaseGroupId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release group id" + }, + { + "name": "releaseId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release id" + }, + { + "name": "path", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Path to find components at" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Paths and counts of Binary Decomposition Components for a Release of a Release Group.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "A directory node with component count", + "properties": { + "type": { + "type": "string", + "enum": [ + "directory" + ], + "description": "Type of component path node (directory or file)" + }, + "name": { + "type": "string", + "description": "Name of directory" + }, + "path": { + "type": "string", + "description": "Path to directory" + }, + "count": { + "type": "number", + "nullable": true, + "description": "Count of component matches in directory" + } + } + }, + { + "type": "object", + "description": "A file node with component revision and root project revision", + "properties": { + "type": { + "type": "string", + "enum": [ + "file" + ], + "description": "Type of component path node (directory or file)" + }, + "name": { + "type": "string", + "description": "Name of file" + }, + "path": { + "type": "string", + "description": "Path to file" + }, + "revisionId": { + "type": "string", + "description": "Dependency revision matched in file" + }, + "componentId": { + "type": "string", + "description": "Component Id for dependency and file" + }, + "packageName": { + "type": "string", + "description": "Package name of Dependency matched in file" + }, + "version": { + "type": "string", + "description": "Version of Dependency matched in file" + }, + "rootProjectRevisionLocator": { + "type": "string", + "description": "Revision of root Binary Decomposition project" + } + } + } + ] + } + } + } + }, + "examples": { + "Example response": { + "value": { + "paths": [ + { + "type": "file", + "name": "aes.py", + "path": "main/crypto/aes.py", + "componentId": "4d24c136-30ea-43b9-a3ef-6613f3eed03b", + "revisionId": "csbinary+python/aes$1.2.3", + "packageName": "aes", + "version": "1.2.3", + "rootProjectRevisionLocator": "binary+uploadedBinaryProject$1746028908005" + }, + { + "type": "directory", + "name": "utils", + "path": "main/crypto/utils", + "count": 10 + }, + { + "type": "directory", + "name": "auth", + "path": "main/crypto/auth", + "count": 4 + }, + { + "type": "file", + "name": "diffie-hellman.py", + "path": "main/crypto/diffie-hellman.py", + "componentId": "4d24c136-30ea-43b9-a3ef-6613f3eed03b", + "revisionId": "csbinary+python/mayo$4.4vbeta", + "packageName": "mayo", + "version": "4.4vbeta", + "rootProjectRevisionLocator": "binary+uploadedBinaryProject$1746028908005" + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Release group ID and release ID are required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release Group not found": { + "value": { + "message": "Release group not found" + } + }, + "Release not found": { + "value": { + "message": "Release not found" + } + }, + "No associated scans found": { + "value": { + "message": "No binary scans found for release" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/release/{releaseId}/dependency-confidence": { + "get": { + "operationId": "getReleaseDependencyConfidence", + "description": "Get Confidence values for the Binary Component Dependencies of a Release of a Release Group", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "releaseId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release id" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A mapping from Binary Component dependencies to Confidence values.", + "content": { + "application/json": { + "schema": { + "type": "object", + "confidences": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + } + }, + "examples": { + "Example response": { + "value": { + "confidences": { + "cs-binary+example/example$1.2.3": "High", + "cs-binary+sample/sample$2.3.4": "Medium", + "cs-binary+dummy/dummy$3.4.5": "Low", + "cs-binary+fake/fake$4.5.6": "Unknown" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Release Id is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release not found": { + "value": { + "message": "Release not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/binary/release/{releaseId}/dependency-confidence/{dependencyLocator}": { + "get": { + "operationId": "getSingleReleaseDependencyConfidence", + "description": "Get Confidence value for a single Binary Component Dependency of a Release", + "tags": [ + "Binary" + ], + "parameters": [ + { + "name": "releaseId", + "in": "path", + "required": true, + "schema": { + "type": "number" + }, + "description": "Release id" + }, + { + "name": "dependencyLocator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Dependency revision" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "A mapping from a single Binary Component dependency to its Confidence value.", + "content": { + "application/json": { + "schema": { + "type": "object", + "confidences": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + } + }, + "examples": { + "Example response": { + "value": { + "confidences": { + "cs-binary+example/example$1.2.3": "High" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing path parameters": { + "value": { + "message": "Release Id is required" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Unauthorized": { + "value": { + "message": "Unauthorized" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Release not found": { + "value": { + "message": "Release not found" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/providers": { + "get": { + "operationId": "listOIDCProviders", + "description": "List OIDC Providers", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "pageSize", + "in": "query", + "description": "Number of providers to return", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10, + "example": 20 + } + }, + { + "name": "prev", + "in": "query", + "description": "ID of the last provider from the previous page for pagination", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "example": 123 + } + }, + { + "name": "filter[scope]", + "description": "Filter providers by scope (org or team). When filtering by team, the `scopeId` parameter must also be provided.\nThe org scope will only return organization-scoped providers. The team scope will return both org-scoped\nproviders as well as team-scoped providers where the scopeId matches the team ID.\n", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "org", + "team" + ], + "example": "team" + } + }, + { + "name": "filter[scopeId]", + "description": "Filter providers by scope ID. Required when the `scope` parameter is `team`.", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "example": 789 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved OIDC Providers", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of results" + }, + "pageSize": { + "type": "integer", + "description": "Number of items requested per page", + "minimum": 1, + "maximum": 50, + "default": 10 + }, + "last": { + "description": "Cursor value of the last item in the results array for pagination" + } + }, + "required": [ + "results", + "pageSize", + "last" + ] + }, + { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Organization-scoped OIDC Provider", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Provider", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this provider belongs to", + "example": 456 + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "org" + ], + "description": "The scope level of the OIDC Provider", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The organization ID", + "example": 789 + }, + "teamName": { + "type": "null", + "description": "Team name (null for org-scoped providers)" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was last updated" + } + }, + "required": [ + "id", + "organizationId", + "issuer", + "scope", + "scopeId", + "createdAt", + "updatedAt" + ] + }, + { + "type": "object", + "description": "Team-scoped OIDC Provider", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Provider", + "example": 124 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this provider belongs to", + "example": 456 + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "team" + ], + "description": "The scope level of the OIDC Provider", + "example": "team" + }, + "scopeId": { + "type": "integer", + "description": "The team ID", + "example": 890 + }, + "teamName": { + "type": "string", + "description": "The name of the team", + "example": "Engineering Team" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was last updated" + } + }, + "required": [ + "id", + "organizationId", + "issuer", + "scope", + "scopeId", + "teamName", + "createdAt", + "updatedAt" + ] + } + ] + }, + "description": "Array of OIDC Providers" + }, + "last": { + "type": "integer", + "description": "ID of the last OIDC provider in the results. Used as the cursor to request the next page." + } + } + } + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createOIDCProvider", + "description": "Create a new OIDC Provider", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "team" + ], + "description": "The scope level of the OIDC Provider", + "example": "team" + }, + "scopeId": { + "type": "integer", + "description": "The ID of the team", + "example": 789 + } + }, + "required": [ + "issuer", + "scope", + "scopeId" + ] + }, + { + "type": "object", + "properties": { + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "org" + ], + "description": "The scope level of the OIDC Provider", + "example": "org" + } + }, + "required": [ + "issuer", + "scope" + ] + } + ] + } + } + } + }, + "responses": { + "201": { + "description": "Successfully created OIDC Provider", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Provider", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this provider belongs to", + "example": 456 + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the OIDC Provider", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 789 + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was last updated" + } + }, + "required": [ + "id", + "organizationId", + "issuer", + "scope", + "scopeId", + "createdAt", + "updatedAt" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/providers/{id}": { + "get": { + "operationId": "getOIDCProvider", + "description": "Get a specific OIDC Provider by ID", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Provider", + "schema": { + "type": "integer", + "example": 123 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved OIDC Provider", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Provider", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this provider belongs to", + "example": 456 + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://oidc.example.com" + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the OIDC Provider", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 789 + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the OIDC Provider was last updated" + } + }, + "required": [ + "id", + "organizationId", + "issuer", + "scope", + "scopeId", + "createdAt", + "updatedAt" + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Provider not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOIDCProvider", + "description": "Delete an OIDC Provider. All associated trust relationships will be deleted as well.", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Provider to delete", + "schema": { + "type": "integer", + "example": 123 + } + } + ], + "responses": { + "204": { + "description": "Successfully deleted OIDC Provider" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Provider not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/providers/{id}/available-service-accounts": { + "get": { + "operationId": "getOIDCProviderAvailableServiceAccounts", + "description": "This endpoint returns service accounts that can be used when creating new trust relationships for an OIDC Provider.\nIf the user making the request has organization-level permission to manage trust relationships, then this will\nreturn all available service accounts. Otherwise, if the user only has team-level permission to manage trust\nrelationships, then a `teamId` query parameter must be provided to filter the available service accounts to only\nthose on the team.\n", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Provider", + "schema": { + "type": "integer", + "example": 123 + } + }, + { + "name": "teamId", + "in": "query", + "description": "The team ID that the service account must be a member of. Required if the user making the request\nonly has team-level permission to manage trust relationships. If the user has organization-level permission then\nthis parameter has no effect.\n", + "required": false, + "schema": { + "type": "integer", + "example": 456 + } + }, + { + "name": "pageSize", + "in": "query", + "description": "Number of service accounts to return", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10, + "example": 20 + } + }, + { + "name": "prev", + "in": "query", + "description": "ID of the last service account from the previous page for pagination", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "example": 789 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved available service accounts", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of available service accounts", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The service account ID", + "example": 789 + }, + "username": { + "type": "string", + "description": "The service account username", + "example": "ci-bot" + }, + "email": { + "type": "string", + "format": "email", + "description": "The service account email", + "example": "ci-bot@example.com" + } + }, + "required": [ + "id", + "username", + "email" + ] + } + }, + "pageSize": { + "type": "integer", + "description": "Number of items requested per page", + "minimum": 1, + "maximum": 50, + "default": 10, + "example": 20 + }, + "last": { + "type": "integer", + "description": "ID of the last service account in the results array for pagination", + "example": 789 + } + }, + "required": [ + "results", + "pageSize", + "last" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Provider not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/trust-relationships": { + "get": { + "operationId": "listOIDCTrustRelationships", + "description": "List OIDC Trust Relationships with optional filtering", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "query", + "description": "Filter by user ID", + "required": false, + "schema": { + "type": "integer", + "example": 789 + } + }, + { + "name": "providerId", + "in": "query", + "description": "Filter by provider ID", + "required": false, + "schema": { + "type": "integer", + "example": 321 + } + }, + { + "name": "pageSize", + "in": "query", + "description": "Number of trust relationships to return", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10, + "example": 20 + } + }, + { + "name": "prev", + "in": "query", + "description": "ID of the last trust relationship from the previous page for pagination", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "example": 456 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved OIDC Trust Relationships", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "type": "object", + "properties": { + "results": { + "type": "array", + "description": "Array of results" + }, + "pageSize": { + "type": "integer", + "description": "Number of items requested per page", + "minimum": 1, + "maximum": 50, + "default": 10 + }, + "last": { + "description": "Cursor value of the last item in the results array for pagination" + } + }, + "required": [ + "results", + "pageSize", + "last" + ] + }, + { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Trust Relationship", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this trust relationship belongs to", + "example": 456 + }, + "userId": { + "type": "integer", + "description": "The ID of the user associated with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider this trust relationship uses", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the trust relationship", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 654 + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://app.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was last updated" + } + }, + "required": [ + "id", + "organizationId", + "userId", + "providerId", + "audiences", + "requiredClaims", + "createdAt", + "updatedAt" + ] + }, + { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "The username of the service account associated with this trust relationship", + "example": "service-account-1" + }, + "email": { + "type": "string", + "description": "The email of the service account associated with this trust relationship (if available)", + "example": "service-account@example.com" + }, + "teamName": { + "type": "string", + "description": "The name of the team (if scope is team)", + "example": "Engineering Team" + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://token.actions.githubusercontent.com" + } + }, + "required": [ + "username", + "teamName", + "issuer" + ] + } + ] + }, + "description": "Array of OIDC Trust Relationships with user, team, and provider details" + }, + "last": { + "type": "integer", + "description": "ID of the last OIDC trust relationship in the results" + } + } + } + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createOIDCTrustRelationship", + "description": "Create a new OIDC Trust Relationship", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The ID of the user to associate with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider to use for this trust relationship", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "org" + ], + "description": "The scope level of the trust relationship", + "example": "org" + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://api.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + } + }, + "required": [ + "userId", + "providerId", + "scope", + "audiences", + "requiredClaims" + ] + }, + { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The ID of the user to associate with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider to use for this trust relationship", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "team" + ], + "description": "The scope level of the trust relationship", + "example": "team" + }, + "scopeId": { + "type": "integer", + "description": "The ID of the team", + "example": 654 + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://api.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + } + }, + "required": [ + "userId", + "providerId", + "scope", + "scopeId", + "audiences", + "requiredClaims" + ] + } + ] + } + } + } + }, + "responses": { + "201": { + "description": "Successfully created OIDC Trust Relationship", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Trust Relationship", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this trust relationship belongs to", + "example": 456 + }, + "userId": { + "type": "integer", + "description": "The ID of the user associated with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider this trust relationship uses", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the trust relationship", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 654 + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://app.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was last updated" + } + }, + "required": [ + "id", + "organizationId", + "userId", + "providerId", + "audiences", + "requiredClaims", + "createdAt", + "updatedAt" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/trust-relationships/{id}": { + "get": { + "operationId": "getOIDCTrustRelationship", + "description": "Get a specific OIDC Trust Relationship by ID", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Trust Relationship", + "schema": { + "type": "integer", + "example": 123 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved OIDC Trust Relationship", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Trust Relationship", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this trust relationship belongs to", + "example": 456 + }, + "userId": { + "type": "integer", + "description": "The ID of the user associated with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider this trust relationship uses", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the trust relationship", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 654 + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://app.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was last updated" + } + }, + "required": [ + "id", + "organizationId", + "userId", + "providerId", + "audiences", + "requiredClaims", + "createdAt", + "updatedAt" + ] + }, + { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "The username of the service account associated with this trust relationship", + "example": "service-account-1" + }, + "email": { + "type": "string", + "description": "The email of the service account associated with this trust relationship (if available)", + "example": "service-account@example.com" + }, + "teamName": { + "type": "string", + "description": "The name of the team (if scope is team)", + "example": "Engineering Team" + }, + "issuer": { + "type": "string", + "description": "The issuer URL of the OIDC Provider", + "example": "https://token.actions.githubusercontent.com" + } + }, + "required": [ + "username", + "teamName", + "issuer" + ] + } + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Trust Relationship not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOIDCTrustRelationship", + "description": "Update an existing OIDC Trust Relationship (only audiences and requiredClaims can be updated)", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Trust Relationship to update", + "schema": { + "type": "integer", + "example": 123 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://app.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "admin", + "value": true, + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successfully updated OIDC Trust Relationship", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the OIDC Trust Relationship", + "example": 123 + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization this trust relationship belongs to", + "example": 456 + }, + "userId": { + "type": "integer", + "description": "The ID of the user associated with this trust relationship", + "example": 789 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider this trust relationship uses", + "example": 321 + }, + "scope": { + "type": "string", + "enum": [ + "org", + "team" + ], + "description": "The scope level of the trust relationship", + "example": "org" + }, + "scopeId": { + "type": "integer", + "description": "The ID associated with the scope: either the organization ID or the team ID", + "example": 654 + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "description": "Array of valid audiences for this trust relationship", + "example": [ + "https://app.fossa.com", + "fossa" + ] + }, + "requiredClaims": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "claim", + "value" + ], + "properties": { + "claim": { + "type": "string", + "description": "The claim type identifier", + "example": "sub" + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ], + "description": "The claim value", + "example": "repo:fossas/*" + }, + "hasWildcards": { + "type": "boolean", + "description": "Whether this claim supports wildcard matching. Defaults to false.\nIf true, then the following characters in `value` are treated as special characters:\n- `?` matches exactly one character\n- `*` matches zero or more characters\n- `\\` escapes the following character\n", + "example": true, + "default": false + } + }, + "additionalProperties": false + }, + "description": "Array of claim objects. Must contain at least one object with claim: \"sub\".\nAdditional objects with other claims are optional.\n", + "example": [ + { + "claim": "sub", + "value": "repo:fossas/*", + "hasWildcards": true + }, + { + "claim": "role", + "value": "admin", + "hasWildcards": false + }, + { + "claim": "department", + "value": "engineering" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was created" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "When the trust relationship was last updated" + } + }, + "required": [ + "id", + "organizationId", + "userId", + "providerId", + "audiences", + "requiredClaims", + "createdAt", + "updatedAt" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Trust Relationship not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOIDCTrustRelationship", + "description": "Delete an OIDC Trust Relationship", + "tags": [ + "OIDC" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the OIDC Trust Relationship to delete", + "schema": { + "type": "integer", + "example": 123 + } + } + ], + "responses": { + "204": { + "description": "Successfully deleted OIDC Trust Relationship" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "OIDC Trust Relationship not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/oidc/token-exchange": { + "post": { + "operationId": "exchangeOIDCToken", + "description": "Exchange an OIDC token for a FOSSA API token", + "tags": [ + "OIDC" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider that issued the token", + "example": 123 + }, + "username": { + "type": "string", + "description": "The username of the user that we want to log in as", + "example": "john.doe" + }, + "token": { + "type": "string", + "description": "The JWT that was issued by the OIDC Provider", + "example": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." + }, + "expiresIn": { + "type": "integer", + "minimum": 900, + "maximum": 43200, + "description": "The desired validity duration of the generated FOSSA token, in seconds. Min 15 minutes (900s), Max 12 hours (43200s), Default 1 hour (3600s).", + "example": 3600, + "default": 3600 + }, + "isPushOnly": { + "type": "boolean", + "description": "Whether the FOSSA token should be push-only. Defaults to true.", + "example": true, + "default": true + } + }, + "required": [ + "providerId", + "username", + "token" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Successfully exchanged OIDC token for FOSSA token", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "integer", + "description": "The ID of the user that the token is for", + "example": 123 + }, + "providerId": { + "type": "integer", + "description": "The ID of the OIDC Provider", + "example": 456 + }, + "issuer": { + "type": "string", + "description": "The issuer of the token", + "example": "https://oidc.example.com" + }, + "subject": { + "type": "string", + "description": "The subject of the token", + "example": "user@example.com" + }, + "credential": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "The FOSSA token that can be used to authenticate with the FOSSA API", + "example": "oidc-abc123def456..." + }, + "isPushOnly": { + "type": "boolean", + "description": "Whether the FOSSA token is push-only", + "example": true + }, + "expiration": { + "type": "string", + "format": "date-time", + "description": "When the FOSSA token expires", + "example": "2024-01-15T10:30:00.000Z" + } + }, + "required": [ + "token", + "isPushOnly", + "expiration" + ], + "description": "The FOSSA credential information" + } + }, + "required": [ + "userId", + "providerId", + "issuer", + "subject", + "credential" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/paths": { + "get": { + "operationId": "getSnippetPaths", + "summary": "Get snippet paths", + "description": "Retrieve file and directory paths where snippets were detected in a revision.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet paths", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "directory", + "file" + ], + "description": "Type of path entry" + }, + "name": { + "type": "string", + "description": "Name of the file or directory" + }, + "path": { + "type": "string", + "description": "Full path to the file or directory" + }, + "count": { + "type": "integer", + "minimum": 0, + "description": "Number of snippets found at this path" + } + }, + "required": [ + "type", + "name", + "path", + "count" + ] + }, + "description": "Array of file and directory paths where snippets were detected" + } + }, + "required": [ + "paths" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets": { + "get": { + "operationId": "getSnippets", + "summary": "Get snippets", + "description": "Retrieve snippets detected in a revision with filtering, sorting, and pagination support.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + }, + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "matchCount_asc", + "matchCount_desc" + ], + "default": "matchCount_desc" + }, + "description": "Sort order for results" + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippets", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the snippet" + }, + "packageId": { + "type": "string", + "description": "Unique identifier for the snippet package" + }, + "purl": { + "type": "string", + "description": "Package URL (purl) for the snippet" + }, + "locator": { + "type": "string", + "description": "The locator for the snippet (optional)" + }, + "package": { + "type": "string", + "description": "Name of the package containing the snippet" + }, + "version": { + "type": "string", + "description": "Version of the package" + }, + "kind": { + "type": "string", + "enum": [ + "snippet", + "file" + ], + "description": "Type of snippet detection (snippet=partial match, file=100% match)" + }, + "matchCount": { + "type": "integer", + "description": "Total number of matches for this snippet" + }, + "highestMatchPercentage": { + "type": "number", + "description": "The highest match percentage across all matches" + }, + "releaseDate": { + "type": "string", + "format": "date-time", + "description": "Release date of the package (optional)" + }, + "homeUrl": { + "type": "string", + "format": "uri", + "description": "Homepage URL of the package (optional)" + }, + "codeUrl": { + "type": "string", + "format": "uri", + "description": "Source code URL of the package (optional)" + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "signature": { + "type": "string", + "description": "License signature or identifier" + }, + "type": { + "type": "string", + "enum": [ + "declared", + "discovered" + ], + "description": "How the license was identified" + }, + "status": { + "type": "string", + "enum": [ + "approved", + "denied", + "flagged", + "unknown" + ], + "description": "Approval status of the license" + }, + "issueId": { + "type": "integer", + "description": "ID of the related issue (optional)" + } + }, + "required": [ + "signature", + "type", + "status" + ] + }, + "description": "Array of licenses associated with the snippet" + }, + "issueCounts": { + "type": "object", + "properties": { + "licensing": { + "type": "object", + "properties": { + "denied": { + "type": "integer", + "minimum": 0, + "description": "Number of denied issues" + }, + "flagged": { + "type": "integer", + "minimum": 0, + "description": "Number of flagged issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown issues" + } + }, + "required": [ + "denied", + "flagged", + "unknown" + ] + }, + "security": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "description": "Number of critical issues" + }, + "high": { + "type": "integer", + "minimum": 0, + "description": "Number of high issues" + }, + "medium": { + "type": "integer", + "minimum": 0, + "description": "Number of medium issues" + }, + "low": { + "type": "integer", + "minimum": 0, + "description": "Number of low issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown severity issues" + } + }, + "required": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + }, + "description": "Issue counts by type" + }, + "rejectionDetails": { + "type": "object", + "properties": { + "rejectedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the snippet was rejected" + }, + "rejectedBy": { + "type": "string", + "description": "User who rejected the snippet (optional)" + } + }, + "required": [ + "rejectedAt" + ] + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + }, + "name": { + "type": "string", + "description": "The name of the label that was assigned to the package." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId", + "name" + ] + }, + "description": "Package labels assigned to this snippet" + } + }, + "required": [ + "id", + "packageId", + "purl", + "locator", + "package", + "version", + "kind", + "matchCount", + "highestMatchPercentage", + "licenses", + "labels", + "issueCounts" + ] + }, + "description": "Array of snippets" + }, + "totalCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of snippets matching the filter criteria" + }, + "page": { + "type": "integer", + "minimum": 1, + "description": "Current page number" + }, + "count": { + "type": "integer", + "minimum": 1, + "description": "Number of items per page" + } + }, + "required": [ + "results", + "totalCount", + "page", + "count" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/count": { + "get": { + "operationId": "getSnippetCount", + "summary": "Get snippet count", + "description": "Get the total count of snippets detected in a revision with optional filtering.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet count", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "The total number of snippets matching the filter criteria" + } + } + }, + "example": { + "count": 42 + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/packages": { + "get": { + "operationId": "getSnippetPackages", + "summary": "Get snippet packages", + "description": "Retrieve snippet packages detected in a revision with filtering, sorting, and pagination support.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + }, + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "matchCount_asc", + "matchCount_desc" + ], + "default": "matchCount_desc" + }, + "description": "Sort order for results" + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet packages", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the snippet package" + }, + "name": { + "type": "string", + "description": "Name of the package" + }, + "versionCount": { + "type": "integer", + "minimum": 0, + "description": "Number of versions detected for this package" + }, + "matchCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of matches for this package across all versions" + }, + "issueCounts": { + "type": "object", + "properties": { + "licensing": { + "type": "object", + "properties": { + "denied": { + "type": "integer", + "minimum": 0, + "description": "Number of denied issues" + }, + "flagged": { + "type": "integer", + "minimum": 0, + "description": "Number of flagged issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown issues" + } + }, + "required": [ + "denied", + "flagged", + "unknown" + ] + }, + "security": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "description": "Number of critical issues" + }, + "high": { + "type": "integer", + "minimum": 0, + "description": "Number of high issues" + }, + "medium": { + "type": "integer", + "minimum": 0, + "description": "Number of medium issues" + }, + "low": { + "type": "integer", + "minimum": 0, + "description": "Number of low issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown severity issues" + } + }, + "required": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + }, + "name": { + "type": "string", + "description": "The name of the label that was assigned to the package." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId", + "name" + ] + }, + "description": "Package labels assigned to this snippet package" + }, + "isFullyRejected": { + "type": "boolean", + "description": "Whether all snippets in this package have been rejected" + } + }, + "required": [ + "id", + "name", + "versionCount", + "matchCount", + "issueCounts", + "labels", + "isFullyRejected" + ] + }, + "description": "Array of snippet packages" + }, + "totalCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of snippet packages matching the filter criteria" + }, + "page": { + "type": "integer", + "minimum": 1, + "description": "Current page number" + }, + "count": { + "type": "integer", + "minimum": 1, + "description": "Number of items per page" + } + }, + "required": [ + "results", + "totalCount", + "page", + "count" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/compare/{olderRevisionLocator}/{status}/paths": { + "get": { + "operationId": "getComparedSnippetPaths", + "summary": "Get compared snippet paths between two revisions", + "description": "Retrieve file and directory paths for the comparison of snippets between two revisions.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The base revision locator" + }, + { + "name": "olderRevisionLocator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "An older revision locator from the same project" + }, + { + "name": "status", + "required": true, + "in": "path", + "schema": { + "type": "string", + "enum": [ + "new", + "removed", + "unchanged" + ] + }, + "description": "The status of snippets to retrieve" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet paths", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "directory", + "file" + ], + "description": "Type of path entry" + }, + "name": { + "type": "string", + "description": "Name of the file or directory" + }, + "path": { + "type": "string", + "description": "Full path to the file or directory" + }, + "count": { + "type": "integer", + "minimum": 0, + "description": "Number of snippets found at this path" + } + }, + "required": [ + "type", + "name", + "path", + "count" + ] + }, + "description": "Array of file and directory paths where snippets were detected" + } + }, + "required": [ + "paths" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/compare/{olderRevisionLocator}/{status}": { + "get": { + "operationId": "getComparedSnippets", + "summary": "Get compared snippets between two revisions", + "description": "Compare snippets between two revisions with filtering, sorting, and pagination support.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The base revision locator" + }, + { + "name": "olderRevisionLocator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "An older revision locator from the same project" + }, + { + "name": "status", + "required": true, + "in": "path", + "schema": { + "type": "string", + "enum": [ + "new", + "removed", + "unchanged" + ] + }, + "description": "The status of snippets to retrieve" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + }, + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "matchCount_asc", + "matchCount_desc" + ], + "default": "matchCount_desc" + }, + "description": "Sort order for results" + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippets", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the snippet" + }, + "packageId": { + "type": "string", + "description": "Unique identifier for the snippet package" + }, + "purl": { + "type": "string", + "description": "Package URL (purl) for the snippet" + }, + "locator": { + "type": "string", + "description": "The locator for the snippet (optional)" + }, + "package": { + "type": "string", + "description": "Name of the package containing the snippet" + }, + "version": { + "type": "string", + "description": "Version of the package" + }, + "kind": { + "type": "string", + "enum": [ + "snippet", + "file" + ], + "description": "Type of snippet detection (snippet=partial match, file=100% match)" + }, + "matchCount": { + "type": "integer", + "description": "Total number of matches for this snippet" + }, + "highestMatchPercentage": { + "type": "number", + "description": "The highest match percentage across all matches" + }, + "releaseDate": { + "type": "string", + "format": "date-time", + "description": "Release date of the package (optional)" + }, + "homeUrl": { + "type": "string", + "format": "uri", + "description": "Homepage URL of the package (optional)" + }, + "codeUrl": { + "type": "string", + "format": "uri", + "description": "Source code URL of the package (optional)" + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "signature": { + "type": "string", + "description": "License signature or identifier" + }, + "type": { + "type": "string", + "enum": [ + "declared", + "discovered" + ], + "description": "How the license was identified" + }, + "status": { + "type": "string", + "enum": [ + "approved", + "denied", + "flagged", + "unknown" + ], + "description": "Approval status of the license" + }, + "issueId": { + "type": "integer", + "description": "ID of the related issue (optional)" + } + }, + "required": [ + "signature", + "type", + "status" + ] + }, + "description": "Array of licenses associated with the snippet" + }, + "issueCounts": { + "type": "object", + "properties": { + "licensing": { + "type": "object", + "properties": { + "denied": { + "type": "integer", + "minimum": 0, + "description": "Number of denied issues" + }, + "flagged": { + "type": "integer", + "minimum": 0, + "description": "Number of flagged issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown issues" + } + }, + "required": [ + "denied", + "flagged", + "unknown" + ] + }, + "security": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "description": "Number of critical issues" + }, + "high": { + "type": "integer", + "minimum": 0, + "description": "Number of high issues" + }, + "medium": { + "type": "integer", + "minimum": 0, + "description": "Number of medium issues" + }, + "low": { + "type": "integer", + "minimum": 0, + "description": "Number of low issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown severity issues" + } + }, + "required": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + }, + "description": "Issue counts by type" + }, + "rejectionDetails": { + "type": "object", + "properties": { + "rejectedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the snippet was rejected" + }, + "rejectedBy": { + "type": "string", + "description": "User who rejected the snippet (optional)" + } + }, + "required": [ + "rejectedAt" + ] + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + }, + "name": { + "type": "string", + "description": "The name of the label that was assigned to the package." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId", + "name" + ] + }, + "description": "Package labels assigned to this snippet" + } + }, + "required": [ + "id", + "packageId", + "purl", + "locator", + "package", + "version", + "kind", + "matchCount", + "highestMatchPercentage", + "licenses", + "labels", + "issueCounts" + ] + }, + "description": "Array of snippets" + }, + "totalCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of snippets matching the filter criteria" + }, + "page": { + "type": "integer", + "minimum": 1, + "description": "Current page number" + }, + "count": { + "type": "integer", + "minimum": 1, + "description": "Number of items per page" + } + }, + "required": [ + "results", + "totalCount", + "page", + "count" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/compare/{olderRevisionLocator}/{status}/packages": { + "get": { + "operationId": "getComparedSnippetPackages", + "summary": "Get compared snippet packages between two revisions", + "description": "Compare snippet packages between two revisions with filtering, sorting, and pagination support.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The base revision locator" + }, + { + "name": "olderRevisionLocator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "An older revision locator from the same project" + }, + { + "name": "status", + "required": true, + "in": "path", + "schema": { + "type": "string", + "enum": [ + "new", + "removed", + "unchanged" + ] + }, + "description": "The status of snippet packages to retrieve" + }, + { + "name": "path", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The path to filter snippets by" + }, + { + "name": "ids", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet IDs" + }, + { + "name": "packageIds", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by specific snippet package IDs" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Search term for filtering snippets by package name" + }, + { + "name": "rejectionStatus", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + } + }, + "description": "Filter by rejection status" + }, + { + "name": "packageLabels", + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Filter by package labels" + }, + { + "name": "sort", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "package_asc", + "package_desc", + "matchCount_asc", + "matchCount_desc" + ], + "default": "matchCount_desc" + }, + "description": "Sort order for results" + }, + { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + { + "name": "pageSize", + "description": "The number of items to return in each page of results", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet packages", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the snippet package" + }, + "name": { + "type": "string", + "description": "Name of the package" + }, + "versionCount": { + "type": "integer", + "minimum": 0, + "description": "Number of versions detected for this package" + }, + "matchCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of matches for this package across all versions" + }, + "issueCounts": { + "type": "object", + "properties": { + "licensing": { + "type": "object", + "properties": { + "denied": { + "type": "integer", + "minimum": 0, + "description": "Number of denied issues" + }, + "flagged": { + "type": "integer", + "minimum": 0, + "description": "Number of flagged issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown issues" + } + }, + "required": [ + "denied", + "flagged", + "unknown" + ] + }, + "security": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "description": "Number of critical issues" + }, + "high": { + "type": "integer", + "minimum": 0, + "description": "Number of high issues" + }, + "medium": { + "type": "integer", + "minimum": 0, + "description": "Number of medium issues" + }, + "low": { + "type": "integer", + "minimum": 0, + "description": "Number of low issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown severity issues" + } + }, + "required": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + } + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + }, + "name": { + "type": "string", + "description": "The name of the label that was assigned to the package." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId", + "name" + ] + }, + "description": "Package labels assigned to this snippet package" + }, + "isFullyRejected": { + "type": "boolean", + "description": "Whether all snippets in this package have been rejected" + } + }, + "required": [ + "id", + "name", + "versionCount", + "matchCount", + "issueCounts", + "labels", + "isFullyRejected" + ] + }, + "description": "Array of snippet packages" + }, + "totalCount": { + "type": "integer", + "minimum": 0, + "description": "Total number of snippet packages matching the filter criteria" + }, + "page": { + "type": "integer", + "minimum": 1, + "description": "Current page number" + }, + "count": { + "type": "integer", + "minimum": 1, + "description": "Number of items per page" + } + }, + "required": [ + "results", + "totalCount", + "page", + "count" + ] + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/{snippetId}": { + "get": { + "operationId": "getSnippetDetails", + "summary": "Get the details of a specific snippet", + "description": "Retrieve a specific snippet's details by its ID.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "snippetId", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The unique identifier of the snippet" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "snippet": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the snippet" + }, + "packageId": { + "type": "string", + "description": "Unique identifier for the snippet package" + }, + "purl": { + "type": "string", + "description": "Package URL (purl) for the snippet" + }, + "locator": { + "type": "string", + "description": "The locator for the snippet (optional)" + }, + "package": { + "type": "string", + "description": "Name of the package containing the snippet" + }, + "version": { + "type": "string", + "description": "Version of the package" + }, + "kind": { + "type": "string", + "enum": [ + "snippet", + "file" + ], + "description": "Type of snippet detection (snippet=partial match, file=100% match)" + }, + "matches": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The file path where the match was detected" + }, + "matchPercentage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Match percentage for this specific match" + }, + "rejectionDetails": { + "type": "object", + "properties": { + "rejectedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the snippet was rejected" + }, + "rejectedBy": { + "type": "string", + "description": "User who rejected the snippet (optional)" + } + }, + "required": [ + "rejectedAt" + ] + } + }, + "required": [ + "path", + "matchPercentage" + ] + }, + "description": "Array of path matches where this snippet was detected" + }, + "highestMatchPercentage": { + "type": "number", + "description": "The highest match percentage across all matches" + }, + "releaseDate": { + "type": "string", + "format": "date-time", + "description": "Release date of the package (optional)" + }, + "homeUrl": { + "type": "string", + "format": "uri", + "description": "Homepage URL of the package (optional)" + }, + "codeUrl": { + "type": "string", + "format": "uri", + "description": "Source code URL of the package (optional)" + }, + "licenses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "signature": { + "type": "string", + "description": "License signature or identifier" + }, + "type": { + "type": "string", + "enum": [ + "declared", + "discovered" + ], + "description": "How the license was identified" + }, + "status": { + "type": "string", + "enum": [ + "approved", + "denied", + "flagged", + "unknown" + ], + "description": "Approval status of the license" + }, + "issueId": { + "type": "integer", + "description": "ID of the related issue (optional)" + } + }, + "required": [ + "signature", + "type", + "status" + ] + }, + "description": "Array of licenses associated with the snippet" + }, + "issueCounts": { + "type": "object", + "properties": { + "licensing": { + "type": "object", + "properties": { + "denied": { + "type": "integer", + "minimum": 0, + "description": "Number of denied issues" + }, + "flagged": { + "type": "integer", + "minimum": 0, + "description": "Number of flagged issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown issues" + } + }, + "required": [ + "denied", + "flagged", + "unknown" + ] + }, + "security": { + "type": "object", + "properties": { + "critical": { + "type": "integer", + "minimum": 0, + "description": "Number of critical issues" + }, + "high": { + "type": "integer", + "minimum": 0, + "description": "Number of high issues" + }, + "medium": { + "type": "integer", + "minimum": 0, + "description": "Number of medium issues" + }, + "low": { + "type": "integer", + "minimum": 0, + "description": "Number of low issues" + }, + "unknown": { + "type": "integer", + "minimum": 0, + "description": "Number of unknown severity issues" + } + }, + "required": [ + "critical", + "high", + "medium", + "low", + "unknown" + ] + } + }, + "description": "Issue counts by type" + }, + "rejectionDetails": { + "type": "object", + "properties": { + "rejectedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the snippet was rejected" + }, + "rejectedBy": { + "type": "string", + "description": "User who rejected the snippet (optional)" + } + }, + "required": [ + "rejectedAt" + ] + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The ID of the package label assignment." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was created." + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time the package label assignment was last updated." + }, + "organizationId": { + "type": "integer", + "description": "The ID of the organization that owns the package label assignment." + }, + "labelId": { + "type": "integer", + "description": "The ID of the label that was assigned to the package." + }, + "packageId": { + "type": "string", + "description": "The ID of the package that the label was assigned to." + }, + "packageVersion": { + "type": "string", + "nullable": true, + "description": "The version of the package that the label was assigned to or null if the label was assigned to all versions." + }, + "scope": { + "type": "string", + "description": "The scope of the package label assignment.", + "enum": [ + "org", + "project", + "revision" + ] + }, + "scopeId": { + "type": "string", + "nullable": true, + "description": "The ID of the scope that the label was assigned to or null if the label was assigned to all scopes." + }, + "name": { + "type": "string", + "description": "The name of the label that was assigned to the package." + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "organizationId", + "labelId", + "packageId", + "scope", + "scopeId", + "name" + ] + }, + "description": "Package labels assigned to this snippet" + }, + "otherVersions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Version of the package" + }, + "matchCount": { + "type": "integer", + "description": "Total number of matches for the snippet in that version" + } + } + }, + "description": "Other versions of the package where this snippet was detected" + } + }, + "required": [ + "id", + "packageId", + "purl", + "locator", + "package", + "version", + "kind", + "matches", + "highestMatchPercentage", + "licenses", + "labels", + "issueCounts" + ] + } + }, + "required": [ + "snippet" + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Snippet not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "SnippetNotFound": { + "value": { + "error": "Snippet not found" + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/{snippetId}/matches/{path}": { + "get": { + "operationId": "getSnippetMatchDetails", + "summary": "Get the details of a specific snippet match", + "description": "Retrieve detailed match information for a snippet at a specific path, including reference and detected code lines.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + }, + { + "name": "snippetId", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The unique identifier of the snippet" + }, + { + "name": "path", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The file path where the snippet match occurred" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved snippet match details", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "matchDetails": { + "allOf": [ + { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The file path where the match was detected" + }, + "matchPercentage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Match percentage for this specific match" + }, + "rejectionDetails": { + "type": "object", + "properties": { + "rejectedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the snippet was rejected" + }, + "rejectedBy": { + "type": "string", + "description": "User who rejected the snippet (optional)" + } + }, + "required": [ + "rejectedAt" + ] + } + }, + "required": [ + "path", + "matchPercentage" + ] + }, + { + "type": "object", + "properties": { + "referenceCode": { + "type": "array", + "items": { + "type": "object", + "properties": { + "line": { + "type": "string", + "description": "The actual code line text" + }, + "lineNumber": { + "type": "integer", + "minimum": 1, + "description": "The line number in the file" + }, + "isHighlighted": { + "type": "boolean", + "description": "Whether this line should be highlighted as part of the match" + } + }, + "required": [ + "line", + "lineNumber", + "isHighlighted" + ] + }, + "description": "Code lines from the reference (third-party) source" + }, + "detectedCode": { + "type": "array", + "items": { + "type": "object", + "properties": { + "line": { + "type": "string", + "description": "The actual code line text" + }, + "lineNumber": { + "type": "integer", + "minimum": 1, + "description": "The line number in the file" + }, + "isHighlighted": { + "type": "boolean", + "description": "Whether this line should be highlighted as part of the match" + } + }, + "required": [ + "line", + "lineNumber", + "isHighlighted" + ] + }, + "description": "Code lines from the detected source in the user's project" + } + }, + "required": [ + "referenceCode", + "detectedCode" + ] + } + ] + } + }, + "required": [ + "matchDetails" + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "Snippet match details not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "SnippetMatchDetailsNotFound": { + "value": { + "error": "Snippet match details not found" + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/reject": { + "post": { + "operationId": "rejectSnippets", + "summary": "Reject snippet matches", + "description": "Reject snippets matching the specified filter criteria.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The path to filter snippets by" + }, + "ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by specific snippet IDs" + }, + "packageIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by specific snippet package IDs" + }, + "search": { + "type": "string", + "description": "Search term for filtering snippets" + }, + "rejectionStatus": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + }, + "description": "Filter by rejection status" + }, + "packageLabels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by package labels" + } + }, + "required": [ + "path" + ] + } + } + } + }, + "responses": { + "204": { + "description": "Snippets rejected successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/revisions/{locator}/snippets/unreject": { + "post": { + "operationId": "unrejectSnippets", + "summary": "Unreject snippet matches", + "description": "Remove rejection status from snippets matching the specified filter criteria.", + "tags": [ + "Snippets" + ], + "parameters": [ + { + "name": "locator", + "required": true, + "in": "path", + "schema": { + "type": "string" + }, + "description": "The revision locator" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The path to filter snippets by" + }, + "ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by specific snippet IDs" + }, + "packageIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by specific snippet package IDs" + }, + "search": { + "type": "string", + "description": "Search term for filtering snippets" + }, + "rejectionStatus": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "rejected", + "unrejected" + ] + }, + "description": "Filter by rejection status" + }, + "packageLabels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by package labels" + } + }, + "required": [ + "path" + ] + } + } + } + }, + "responses": { + "204": { + "description": "Snippets unrejected successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request Parameter/Body": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error at root.X: ...", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + } + } + } + }, + "/report-options": { + "get": { + "operationId": "getAllReportOptions", + "description": "Get all saved report options for the authenticated user's organization. Requires permission to create reports for any project or release group.", + "tags": [ + "Report Options" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "page", + "description": "The page number for pagination (1-indexed)", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + }, + "example": 1 + }, + { + "name": "pageSize", + "description": "The number of items per page", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 50 + }, + "example": 50 + } + ], + "responses": { + "200": { + "description": "A paginated list of saved report options", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "description": "A saved report configuration template", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the report option", + "example": 1 + }, + "name": { + "type": "string", + "description": "Name of the saved report option", + "example": "My Custom Report" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that owns this report option", + "example": 100 + }, + "options": { + "type": "object", + "description": "Configuration options for customizing report generation", + "properties": { + "sections": { + "type": "object", + "description": "Controls which sections are included in the report", + "properties": { + "projectDeclaredLicenses": { + "type": "boolean", + "description": "Include project declared licenses section" + }, + "firstPartyLicenses": { + "type": "boolean", + "description": "Include first party licenses section" + }, + "licenseList": { + "type": "boolean", + "description": "Include license list section" + }, + "directDependencies": { + "type": "boolean", + "description": "Include direct dependencies section" + }, + "deepDependencies": { + "type": "boolean", + "description": "Include deep dependencies section" + }, + "snippetDependencies": { + "type": "boolean", + "description": "Include snippet dependencies section" + }, + "copyrightList": { + "type": "boolean", + "description": "Include copyright list section" + } + }, + "required": [ + "projectDeclaredLicenses", + "firstPartyLicenses", + "licenseList", + "directDependencies", + "deepDependencies", + "snippetDependencies", + "copyrightList" + ] + }, + "toggles": { + "type": "object", + "description": "Feature toggles for report generation", + "properties": { + "useHashAndVersionData": { + "type": "boolean", + "description": "Include hash and version data in the report" + } + }, + "required": [ + "useHashAndVersionData" + ] + }, + "excludeFields": { + "type": "object", + "description": "Fields to exclude from the report", + "properties": { + "packageLabels": { + "type": "array", + "description": "List of package label IDs to exclude from the report", + "items": { + "type": "integer" + } + } + }, + "required": [ + "packageLabels" + ] + }, + "dependencyData": { + "type": "object", + "description": "Controls which dependency data fields are included", + "properties": { + "projects": { + "type": "boolean", + "description": "For release group reports, show which projects the dependency is present in" + }, + "name": { + "type": "boolean", + "description": "The name of the dependency" + }, + "authors": { + "type": "boolean", + "description": "The authors of the dependency" + }, + "description": { + "type": "boolean", + "description": "The description of the dependency" + }, + "homepage": { + "type": "boolean", + "description": "The homepage of the dependency" + }, + "packageManager": { + "type": "boolean", + "description": "The package manager of the dependency" + }, + "downloadUrl": { + "type": "boolean", + "description": "The download URL of the dependency" + }, + "concludedLicenses": { + "type": "boolean", + "description": "The concluded licenses of the dependency" + }, + "declaredLicenses": { + "type": "boolean", + "description": "The declared licenses of the dependency" + }, + "discoveredLicenses": { + "type": "boolean", + "description": "The discovered licenses of the dependency" + }, + "copyrights": { + "type": "boolean", + "description": "The copyrights of the dependency" + }, + "licenseUrl": { + "type": "boolean", + "description": "The license URL of the dependency" + }, + "licenseFileMatches": { + "type": "boolean", + "description": "The list of files that the license was discovered in" + }, + "issueResolutionNotes": { + "type": "boolean", + "description": "Issue resolution notes" + }, + "packageLabels": { + "type": "boolean", + "description": "Package labels" + }, + "dependencyPaths": { + "type": "boolean", + "description": "The origin paths of the dependency (what files the dependency was defined/found in)" + }, + "filePaths": { + "type": "boolean", + "description": "The paths_to of the dependency (the chain of dependencies that brought it into the project)" + }, + "noticeFiles": { + "type": "boolean", + "description": "Notice files" + }, + "fullLicenseText": { + "type": "boolean", + "description": "Full license text" + } + }, + "required": [ + "projects", + "name", + "authors", + "description", + "homepage", + "packageManager", + "downloadUrl", + "concludedLicenses", + "declaredLicenses", + "discoveredLicenses", + "copyrights", + "licenseUrl", + "licenseFileMatches", + "issueResolutionNotes", + "packageLabels", + "dependencyPaths", + "filePaths", + "noticeFiles", + "fullLicenseText" + ] + } + }, + "required": [ + "sections", + "toggles", + "excludeFields", + "dependencyData" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was created", + "example": "2024-01-15T10:30:00.000Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was last updated", + "example": "2024-01-15T10:30:00.000Z" + } + }, + "required": [ + "id", + "name", + "organizationId", + "options", + "createdAt", + "updatedAt" + ] + } + }, + "page": { + "type": "integer", + "description": "Current page number", + "example": 1 + }, + "pageSize": { + "type": "integer", + "description": "Number of items per page", + "example": 50 + }, + "total": { + "type": "integer", + "description": "Total number of report options", + "example": 100 + } + }, + "required": [ + "results", + "page", + "pageSize", + "total" + ] + }, + "examples": { + "Paginated report options": { + "value": { + "results": [ + { + "id": 1, + "name": "Standard Report", + "organizationId": 100, + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": false, + "snippetDependencies": false, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": false + }, + "excludeFields": { + "packageLabels": [] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": false, + "description": true, + "homepage": false, + "packageManager": true, + "downloadUrl": false, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": false, + "licenseFileMatches": false, + "issueResolutionNotes": false, + "packageLabels": false, + "dependencyPaths": false, + "filePaths": false, + "noticeFiles": false, + "fullLicenseText": false + } + }, + "createdAt": "2024-01-15T10:30:00.000Z", + "updatedAt": "2024-01-15T10:30:00.000Z" + }, + { + "id": 2, + "name": "Custom Report", + "organizationId": 100, + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": true, + "snippetDependencies": true, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": true + }, + "excludeFields": { + "packageLabels": [ + 1, + 2 + ] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": true, + "description": true, + "homepage": true, + "packageManager": true, + "downloadUrl": true, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": true, + "licenseFileMatches": true, + "issueResolutionNotes": true, + "packageLabels": true, + "dependencyPaths": true, + "filePaths": true, + "noticeFiles": true, + "fullLicenseText": true + } + }, + "createdAt": "2024-01-16T14:20:00.000Z", + "updatedAt": "2024-01-16T14:20:00.000Z" + } + ], + "page": 1, + "pageSize": 50, + "total": 2 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid page parameter": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "page must be a positive integer", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createReportOption", + "description": "Create a new saved report option for the authenticated user's organization. Requires permission to save report options (ReportOptionAny or TeamReportOptionAny).", + "tags": [ + "Report Options" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Request body for creating a new report option", + "properties": { + "name": { + "type": "string", + "description": "Name of the report option (1-80 characters). Must be unique within the organization.", + "minLength": 1, + "maxLength": 80, + "example": "My Custom Report" + }, + "options": { + "type": "object", + "description": "Configuration options for customizing report generation", + "properties": { + "sections": { + "type": "object", + "description": "Controls which sections are included in the report", + "properties": { + "projectDeclaredLicenses": { + "type": "boolean", + "description": "Include project declared licenses section" + }, + "firstPartyLicenses": { + "type": "boolean", + "description": "Include first party licenses section" + }, + "licenseList": { + "type": "boolean", + "description": "Include license list section" + }, + "directDependencies": { + "type": "boolean", + "description": "Include direct dependencies section" + }, + "deepDependencies": { + "type": "boolean", + "description": "Include deep dependencies section" + }, + "snippetDependencies": { + "type": "boolean", + "description": "Include snippet dependencies section" + }, + "copyrightList": { + "type": "boolean", + "description": "Include copyright list section" + } + }, + "required": [ + "projectDeclaredLicenses", + "firstPartyLicenses", + "licenseList", + "directDependencies", + "deepDependencies", + "snippetDependencies", + "copyrightList" + ] + }, + "toggles": { + "type": "object", + "description": "Feature toggles for report generation", + "properties": { + "useHashAndVersionData": { + "type": "boolean", + "description": "Include hash and version data in the report" + } + }, + "required": [ + "useHashAndVersionData" + ] + }, + "excludeFields": { + "type": "object", + "description": "Fields to exclude from the report", + "properties": { + "packageLabels": { + "type": "array", + "description": "List of package label IDs to exclude from the report", + "items": { + "type": "integer" + } + } + }, + "required": [ + "packageLabels" + ] + }, + "dependencyData": { + "type": "object", + "description": "Controls which dependency data fields are included", + "properties": { + "projects": { + "type": "boolean", + "description": "For release group reports, show which projects the dependency is present in" + }, + "name": { + "type": "boolean", + "description": "The name of the dependency" + }, + "authors": { + "type": "boolean", + "description": "The authors of the dependency" + }, + "description": { + "type": "boolean", + "description": "The description of the dependency" + }, + "homepage": { + "type": "boolean", + "description": "The homepage of the dependency" + }, + "packageManager": { + "type": "boolean", + "description": "The package manager of the dependency" + }, + "downloadUrl": { + "type": "boolean", + "description": "The download URL of the dependency" + }, + "concludedLicenses": { + "type": "boolean", + "description": "The concluded licenses of the dependency" + }, + "declaredLicenses": { + "type": "boolean", + "description": "The declared licenses of the dependency" + }, + "discoveredLicenses": { + "type": "boolean", + "description": "The discovered licenses of the dependency" + }, + "copyrights": { + "type": "boolean", + "description": "The copyrights of the dependency" + }, + "licenseUrl": { + "type": "boolean", + "description": "The license URL of the dependency" + }, + "licenseFileMatches": { + "type": "boolean", + "description": "The list of files that the license was discovered in" + }, + "issueResolutionNotes": { + "type": "boolean", + "description": "Issue resolution notes" + }, + "packageLabels": { + "type": "boolean", + "description": "Package labels" + }, + "dependencyPaths": { + "type": "boolean", + "description": "The origin paths of the dependency (what files the dependency was defined/found in)" + }, + "filePaths": { + "type": "boolean", + "description": "The paths_to of the dependency (the chain of dependencies that brought it into the project)" + }, + "noticeFiles": { + "type": "boolean", + "description": "Notice files" + }, + "fullLicenseText": { + "type": "boolean", + "description": "Full license text" + } + }, + "required": [ + "projects", + "name", + "authors", + "description", + "homepage", + "packageManager", + "downloadUrl", + "concludedLicenses", + "declaredLicenses", + "discoveredLicenses", + "copyrights", + "licenseUrl", + "licenseFileMatches", + "issueResolutionNotes", + "packageLabels", + "dependencyPaths", + "filePaths", + "noticeFiles", + "fullLicenseText" + ] + } + }, + "required": [ + "sections", + "toggles", + "excludeFields", + "dependencyData" + ] + } + }, + "required": [ + "name", + "options" + ] + }, + "examples": { + "Standard Report": { + "value": { + "name": "Standard Report", + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": false, + "snippetDependencies": false, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": false + }, + "excludeFields": { + "packageLabels": [] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": false, + "description": true, + "homepage": false, + "packageManager": true, + "downloadUrl": false, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": false, + "licenseFileMatches": false, + "issueResolutionNotes": false, + "packageLabels": false, + "dependencyPaths": false, + "filePaths": false, + "noticeFiles": false, + "fullLicenseText": false + } + } + } + }, + "Detailed Report": { + "value": { + "name": "Custom Report", + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": true, + "snippetDependencies": true, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": true + }, + "excludeFields": { + "packageLabels": [ + 1, + 2, + 3 + ] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": true, + "description": true, + "homepage": true, + "packageManager": true, + "downloadUrl": true, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": true, + "licenseFileMatches": true, + "issueResolutionNotes": true, + "packageLabels": true, + "dependencyPaths": true, + "filePaths": true, + "noticeFiles": true, + "fullLicenseText": true + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Report option created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A saved report configuration template", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the report option", + "example": 1 + }, + "name": { + "type": "string", + "description": "Name of the saved report option", + "example": "My Custom Report" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that owns this report option", + "example": 100 + }, + "options": { + "type": "object", + "description": "Configuration options for customizing report generation", + "properties": { + "sections": { + "type": "object", + "description": "Controls which sections are included in the report", + "properties": { + "projectDeclaredLicenses": { + "type": "boolean", + "description": "Include project declared licenses section" + }, + "firstPartyLicenses": { + "type": "boolean", + "description": "Include first party licenses section" + }, + "licenseList": { + "type": "boolean", + "description": "Include license list section" + }, + "directDependencies": { + "type": "boolean", + "description": "Include direct dependencies section" + }, + "deepDependencies": { + "type": "boolean", + "description": "Include deep dependencies section" + }, + "snippetDependencies": { + "type": "boolean", + "description": "Include snippet dependencies section" + }, + "copyrightList": { + "type": "boolean", + "description": "Include copyright list section" + } + }, + "required": [ + "projectDeclaredLicenses", + "firstPartyLicenses", + "licenseList", + "directDependencies", + "deepDependencies", + "snippetDependencies", + "copyrightList" + ] + }, + "toggles": { + "type": "object", + "description": "Feature toggles for report generation", + "properties": { + "useHashAndVersionData": { + "type": "boolean", + "description": "Include hash and version data in the report" + } + }, + "required": [ + "useHashAndVersionData" + ] + }, + "excludeFields": { + "type": "object", + "description": "Fields to exclude from the report", + "properties": { + "packageLabels": { + "type": "array", + "description": "List of package label IDs to exclude from the report", + "items": { + "type": "integer" + } + } + }, + "required": [ + "packageLabels" + ] + }, + "dependencyData": { + "type": "object", + "description": "Controls which dependency data fields are included", + "properties": { + "projects": { + "type": "boolean", + "description": "For release group reports, show which projects the dependency is present in" + }, + "name": { + "type": "boolean", + "description": "The name of the dependency" + }, + "authors": { + "type": "boolean", + "description": "The authors of the dependency" + }, + "description": { + "type": "boolean", + "description": "The description of the dependency" + }, + "homepage": { + "type": "boolean", + "description": "The homepage of the dependency" + }, + "packageManager": { + "type": "boolean", + "description": "The package manager of the dependency" + }, + "downloadUrl": { + "type": "boolean", + "description": "The download URL of the dependency" + }, + "concludedLicenses": { + "type": "boolean", + "description": "The concluded licenses of the dependency" + }, + "declaredLicenses": { + "type": "boolean", + "description": "The declared licenses of the dependency" + }, + "discoveredLicenses": { + "type": "boolean", + "description": "The discovered licenses of the dependency" + }, + "copyrights": { + "type": "boolean", + "description": "The copyrights of the dependency" + }, + "licenseUrl": { + "type": "boolean", + "description": "The license URL of the dependency" + }, + "licenseFileMatches": { + "type": "boolean", + "description": "The list of files that the license was discovered in" + }, + "issueResolutionNotes": { + "type": "boolean", + "description": "Issue resolution notes" + }, + "packageLabels": { + "type": "boolean", + "description": "Package labels" + }, + "dependencyPaths": { + "type": "boolean", + "description": "The origin paths of the dependency (what files the dependency was defined/found in)" + }, + "filePaths": { + "type": "boolean", + "description": "The paths_to of the dependency (the chain of dependencies that brought it into the project)" + }, + "noticeFiles": { + "type": "boolean", + "description": "Notice files" + }, + "fullLicenseText": { + "type": "boolean", + "description": "Full license text" + } + }, + "required": [ + "projects", + "name", + "authors", + "description", + "homepage", + "packageManager", + "downloadUrl", + "concludedLicenses", + "declaredLicenses", + "discoveredLicenses", + "copyrights", + "licenseUrl", + "licenseFileMatches", + "issueResolutionNotes", + "packageLabels", + "dependencyPaths", + "filePaths", + "noticeFiles", + "fullLicenseText" + ] + } + }, + "required": [ + "sections", + "toggles", + "excludeFields", + "dependencyData" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was created", + "example": "2024-01-15T10:30:00.000Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was last updated", + "example": "2024-01-15T10:30:00.000Z" + } + }, + "required": [ + "id", + "name", + "organizationId", + "options", + "createdAt", + "updatedAt" + ] + }, + "examples": { + "Standard Report": { + "value": { + "id": 1, + "name": "Standard Report", + "organizationId": 100, + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": false, + "snippetDependencies": false, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": false + }, + "excludeFields": { + "packageLabels": [] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": false, + "description": true, + "homepage": false, + "packageManager": true, + "downloadUrl": false, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": false, + "licenseFileMatches": false, + "issueResolutionNotes": false, + "packageLabels": false, + "dependencyPaths": false, + "filePaths": false, + "noticeFiles": false, + "fullLicenseText": false + } + }, + "createdAt": "2024-01-15T10:30:00.000Z", + "updatedAt": "2024-01-15T10:30:00.000Z" + } + }, + "Detailed Report": { + "value": { + "id": 2, + "name": "Custom Report", + "organizationId": 100, + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": true, + "snippetDependencies": true, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": true + }, + "excludeFields": { + "packageLabels": [ + 1, + 2 + ] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": true, + "description": true, + "homepage": true, + "packageManager": true, + "downloadUrl": true, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": true, + "licenseFileMatches": true, + "issueResolutionNotes": true, + "packageLabels": true, + "dependencyPaths": true, + "filePaths": true, + "noticeFiles": true, + "fullLicenseText": true + } + }, + "createdAt": "2024-01-16T14:20:00.000Z", + "updatedAt": "2024-01-16T14:20:00.000Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Invalid input or duplicate name", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Missing name": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Required at \"name\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Empty name": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: String must contain at least 1 character(s) at \"name\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Name too long": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: String must contain at most 80 character(s) at \"name\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Duplicate name": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "A report option with the name \"My Custom Report\" already exists", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Missing options": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Required at \"options\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid options type": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Invalid input: expected object, received string at \"options\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Missing required section": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Invalid input: expected object, received undefined at \"options.sections\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid field type": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Invalid input: expected boolean, received string at \"options.sections.projectDeclaredLicenses\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden - User lacks permission to save report options", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Insufficient permissions": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2002, + "message": "User does not have permission to save report options", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Feature flag disabled": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2002, + "message": "savedReportOptions is not enabled in this organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/report-options/{id}": { + "put": { + "operationId": "updateReportOptionById", + "description": "Update an existing saved report option by ID. Supports partial updates - only the fields provided will be updated, with deep merging for nested options. Requires permission to edit report options (ReportOptionAny or TeamReportOptionAny).", + "tags": [ + "Report Options" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "description": "The unique identifier of the report option to update", + "required": true, + "in": "path", + "schema": { + "type": "integer" + }, + "example": 1 + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Request body for updating an existing report option. Supports partial updates with deep merging.", + "properties": { + "name": { + "type": "string", + "description": "Name of the report option (1-80 characters). Must be unique within the organization.", + "minLength": 1, + "maxLength": 80, + "example": "Updated Report Name" + }, + "options": { + "type": "object", + "description": "Partial report configuration. Only provided fields will be updated, with deep merging applied.", + "properties": { + "sections": { + "type": "object", + "description": "Controls which sections are included in the report", + "properties": { + "projectDeclaredLicenses": { + "type": "boolean" + }, + "firstPartyLicenses": { + "type": "boolean" + }, + "licenseList": { + "type": "boolean" + }, + "directDependencies": { + "type": "boolean" + }, + "deepDependencies": { + "type": "boolean" + }, + "snippetDependencies": { + "type": "boolean" + }, + "copyrightList": { + "type": "boolean" + } + } + }, + "toggles": { + "type": "object", + "description": "Feature toggles for report generation", + "properties": { + "useHashAndVersionData": { + "type": "boolean" + } + } + }, + "excludeFields": { + "type": "object", + "description": "Fields to exclude from the report", + "properties": { + "packageLabels": { + "type": "array", + "description": "List of package label IDs to exclude", + "items": { + "type": "integer" + } + } + } + }, + "dependencyData": { + "type": "object", + "description": "Controls which dependency data fields are included", + "properties": { + "projects": { + "type": "boolean" + }, + "name": { + "type": "boolean" + }, + "authors": { + "type": "boolean" + }, + "description": { + "type": "boolean" + }, + "homepage": { + "type": "boolean" + }, + "packageManager": { + "type": "boolean" + }, + "downloadUrl": { + "type": "boolean" + }, + "concludedLicenses": { + "type": "boolean" + }, + "declaredLicenses": { + "type": "boolean" + }, + "discoveredLicenses": { + "type": "boolean" + }, + "copyrights": { + "type": "boolean" + }, + "licenseUrl": { + "type": "boolean" + }, + "licenseFileMatches": { + "type": "boolean" + }, + "issueResolutionNotes": { + "type": "boolean" + }, + "packageLabels": { + "type": "boolean" + }, + "dependencyPaths": { + "type": "boolean" + }, + "filePaths": { + "type": "boolean" + }, + "noticeFiles": { + "type": "boolean" + }, + "fullLicenseText": { + "type": "boolean" + } + } + } + } + } + } + }, + "examples": { + "Update name only": { + "value": { + "name": "My Updated Report" + } + }, + "Update single field": { + "value": { + "options": { + "sections": { + "copyrightList": true + } + } + } + }, + "Update multiple fields": { + "value": { + "name": "Comprehensive Report", + "options": { + "dependencyData": { + "authors": false, + "homepage": false + } + } + } + }, + "Empty update": { + "value": {} + } + } + } + } + }, + "responses": { + "200": { + "description": "Report option updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A saved report configuration template", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the report option", + "example": 1 + }, + "name": { + "type": "string", + "description": "Name of the saved report option", + "example": "My Custom Report" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that owns this report option", + "example": 100 + }, + "options": { + "type": "object", + "description": "Configuration options for customizing report generation", + "properties": { + "sections": { + "type": "object", + "description": "Controls which sections are included in the report", + "properties": { + "projectDeclaredLicenses": { + "type": "boolean", + "description": "Include project declared licenses section" + }, + "firstPartyLicenses": { + "type": "boolean", + "description": "Include first party licenses section" + }, + "licenseList": { + "type": "boolean", + "description": "Include license list section" + }, + "directDependencies": { + "type": "boolean", + "description": "Include direct dependencies section" + }, + "deepDependencies": { + "type": "boolean", + "description": "Include deep dependencies section" + }, + "snippetDependencies": { + "type": "boolean", + "description": "Include snippet dependencies section" + }, + "copyrightList": { + "type": "boolean", + "description": "Include copyright list section" + } + }, + "required": [ + "projectDeclaredLicenses", + "firstPartyLicenses", + "licenseList", + "directDependencies", + "deepDependencies", + "snippetDependencies", + "copyrightList" + ] + }, + "toggles": { + "type": "object", + "description": "Feature toggles for report generation", + "properties": { + "useHashAndVersionData": { + "type": "boolean", + "description": "Include hash and version data in the report" + } + }, + "required": [ + "useHashAndVersionData" + ] + }, + "excludeFields": { + "type": "object", + "description": "Fields to exclude from the report", + "properties": { + "packageLabels": { + "type": "array", + "description": "List of package label IDs to exclude from the report", + "items": { + "type": "integer" + } + } + }, + "required": [ + "packageLabels" + ] + }, + "dependencyData": { + "type": "object", + "description": "Controls which dependency data fields are included", + "properties": { + "projects": { + "type": "boolean", + "description": "For release group reports, show which projects the dependency is present in" + }, + "name": { + "type": "boolean", + "description": "The name of the dependency" + }, + "authors": { + "type": "boolean", + "description": "The authors of the dependency" + }, + "description": { + "type": "boolean", + "description": "The description of the dependency" + }, + "homepage": { + "type": "boolean", + "description": "The homepage of the dependency" + }, + "packageManager": { + "type": "boolean", + "description": "The package manager of the dependency" + }, + "downloadUrl": { + "type": "boolean", + "description": "The download URL of the dependency" + }, + "concludedLicenses": { + "type": "boolean", + "description": "The concluded licenses of the dependency" + }, + "declaredLicenses": { + "type": "boolean", + "description": "The declared licenses of the dependency" + }, + "discoveredLicenses": { + "type": "boolean", + "description": "The discovered licenses of the dependency" + }, + "copyrights": { + "type": "boolean", + "description": "The copyrights of the dependency" + }, + "licenseUrl": { + "type": "boolean", + "description": "The license URL of the dependency" + }, + "licenseFileMatches": { + "type": "boolean", + "description": "The list of files that the license was discovered in" + }, + "issueResolutionNotes": { + "type": "boolean", + "description": "Issue resolution notes" + }, + "packageLabels": { + "type": "boolean", + "description": "Package labels" + }, + "dependencyPaths": { + "type": "boolean", + "description": "The origin paths of the dependency (what files the dependency was defined/found in)" + }, + "filePaths": { + "type": "boolean", + "description": "The paths_to of the dependency (the chain of dependencies that brought it into the project)" + }, + "noticeFiles": { + "type": "boolean", + "description": "Notice files" + }, + "fullLicenseText": { + "type": "boolean", + "description": "Full license text" + } + }, + "required": [ + "projects", + "name", + "authors", + "description", + "homepage", + "packageManager", + "downloadUrl", + "concludedLicenses", + "declaredLicenses", + "discoveredLicenses", + "copyrights", + "licenseUrl", + "licenseFileMatches", + "issueResolutionNotes", + "packageLabels", + "dependencyPaths", + "filePaths", + "noticeFiles", + "fullLicenseText" + ] + } + }, + "required": [ + "sections", + "toggles", + "excludeFields", + "dependencyData" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was created", + "example": "2024-01-15T10:30:00.000Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the report option was last updated", + "example": "2024-01-15T10:30:00.000Z" + } + }, + "required": [ + "id", + "name", + "organizationId", + "options", + "createdAt", + "updatedAt" + ] + }, + "examples": { + "Updated report option": { + "value": { + "id": 1, + "name": "Standard Report", + "organizationId": 100, + "options": { + "sections": { + "projectDeclaredLicenses": true, + "firstPartyLicenses": true, + "licenseList": true, + "directDependencies": true, + "deepDependencies": false, + "snippetDependencies": false, + "copyrightList": true + }, + "toggles": { + "useHashAndVersionData": false + }, + "excludeFields": { + "packageLabels": [] + }, + "dependencyData": { + "projects": true, + "name": true, + "authors": false, + "description": true, + "homepage": false, + "packageManager": true, + "downloadUrl": false, + "concludedLicenses": true, + "declaredLicenses": true, + "discoveredLicenses": true, + "copyrights": true, + "licenseUrl": false, + "licenseFileMatches": false, + "issueResolutionNotes": false, + "packageLabels": false, + "dependencyPaths": false, + "filePaths": false, + "noticeFiles": false, + "fullLicenseText": false + } + }, + "createdAt": "2024-01-15T10:30:00.000Z", + "updatedAt": "2024-01-15T10:30:00.000Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Invalid input or duplicate name", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Empty name": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Too small: expected string to have >=1 characters at \"name\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Name too long": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Too big: expected string to have <=80 characters at \"name\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Duplicate name": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "A report option with the name \"My Updated Report\" already exists", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "Invalid field type": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Validation error: Invalid input: expected boolean, received string at \"options.sections.copyrightList\"", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden - User lacks permission or report option not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Insufficient permissions": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to edit report options", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Report option not found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "Report option not found in this organization", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Feature flag disabled": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2002, + "message": "savedReportOptions is not enabled in this organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteReportOptionById", + "description": "Delete a saved report option by ID. Requires permission to delete report options (ReportOptionAny or TeamReportOptionAny with Delete action).", + "tags": [ + "Report Options" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "description": "The unique identifier of the report option to delete", + "required": true, + "in": "path", + "schema": { + "type": "integer" + }, + "example": 1 + } + ], + "responses": { + "204": { + "description": "Report option deleted successfully. No content returned." + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden - User lacks permission or report option not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Insufficient permissions": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to delete report options", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Report option not found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "Report option not found in this organization", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + }, + "Feature flag disabled": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2002, + "message": "savedReportOptions is not enabled in this organization.", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/notifications": { + "get": { + "operationId": "getOrganizationNotificationSettings", + "description": "Get notification settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "notificationDefaultEnabled": { + "type": "boolean", + "description": "the on/off status of project notifications" + }, + "notificationDefaultSlackScan": { + "type": "boolean", + "description": "the on/off status of slack notifications for scans" + }, + "notificationDefaultEmailScanUsers": { + "type": "array", + "items": { + "type": "number", + "description": "the list of user ids to email for scan notifications" + } + }, + "notificationDefaultEmailScanUserType": { + "type": "string", + "description": "The type of users to email for scan notifications. Each option represents a different set of users:\n- current: Only the current user will receive scan notifications.\n- all: All users will receive scan notifications.\n- custom: Custom set of users will receive scan notifications.\n", + "enum": [ + "current", + "all", + "custom" + ] + } + } + }, + "examples": { + "NotificationsSettings": { + "value": { + "notificationDefaultEnabled": true, + "notificationDefaultSlackScan": true, + "notificationDefaultEmailScanUsers": [ + 1, + 2 + ], + "notificationDefaultEmailScanUserType": "all" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationNotificationSettings", + "description": "Update notification settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "notificationDefaultEnabled": { + "type": "boolean", + "description": "the on/off status of project notifications" + }, + "notificationDefaultSlackScan": { + "type": "boolean", + "description": "the on/off status of slack notifications for scans" + }, + "notificationDefaultEmailScanUsers": { + "type": "array", + "items": { + "type": "number", + "description": "the list of user ids to email for scan notifications" + } + }, + "notificationDefaultEmailScanUserType": { + "type": "string", + "description": "The type of users to email for scan notifications. Each option represents a different set of users:\n- current: Only the current user will receive scan notifications.\n- all: All users will receive scan notifications.\n- custom: Custom set of users will receive scan notifications.\n", + "enum": [ + "current", + "all", + "custom" + ] + } + } + }, + "examples": { + "NotificationsSettings": { + "value": { + "notificationDefaultEnabled": true, + "notificationDefaultSlackScan": true, + "notificationDefaultEmailScanUsers": [ + 1, + 2 + ], + "notificationDefaultEmailScanUserType": "all" + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationNotificationSettings", + "description": "Propagate notification settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "notificationDefaultEmailScanUsers", + "notificationDefaultEmailBuildUsers", + "notificationDefaultSlackScan", + "notificationDefaultSlackBuild" + ] + }, + "example": [ + "notificationDefaultEmailScanUsers", + "notificationDefaultEmailBuildUsers", + "notificationDefaultSlackScan", + "notificationDefaultSlackBuild" + ] + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/projects/update-hooks": { + "get": { + "operationId": "getOrganizationUpdateHookSettings", + "description": "Get project update hook settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "updateHookDefaultScheduledEnabled": { + "type": "boolean", + "description": "the on/off status of if the update hook is enabled" + }, + "updateHookDefaultScheduledInterval": { + "type": "string", + "enum": [ + "hour", + "day", + "week" + ], + "nullable": true, + "description": "the cadence of the updates" + }, + "updateHookDefaultScheduledIntervalLength": { + "type": "integer", + "nullable": true, + "description": "the cadence of the scheduled updates" + }, + "updateHookDefaultScheduledIntervalTime": { + "type": "string", + "nullable": true, + "description": "date/time for the schedule update hook intervals" + } + } + }, + "examples": { + "ProjectUpdateHooksSettings": { + "value": { + "updateHookDefaultScheduledEnabled": true, + "updateHookDefaultScheduledInterval": "week", + "updateHookDefaultScheduledIntervalLength": 77, + "updateHookDefaultScheduledIntervalTime": "2023-09-22T10:30:00Z" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationUpdateHookSettings", + "description": "Update project update hook settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "updateHookDefaultScheduledEnabled": { + "type": "boolean", + "description": "the on/off status of if the update hook is enabled" + }, + "updateHookDefaultScheduledInterval": { + "type": "string", + "enum": [ + "hour", + "day", + "week" + ], + "nullable": true, + "description": "the cadence of the updates" + }, + "updateHookDefaultScheduledIntervalLength": { + "type": "integer", + "nullable": true, + "description": "the cadence of the scheduled updates" + }, + "updateHookDefaultScheduledIntervalTime": { + "type": "string", + "nullable": true, + "description": "date/time for the schedule update hook intervals" + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "propagateOrganizationUpdateHookSettings", + "description": "Propagate project update hook settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "updateHookDefaultScheduledEnabled", + "updateHookDefaultScheduledInterval", + "updateHookDefaultScheduledIntervalLength", + "updateHookDefaultScheduledIntervalTime" + ] + } + }, + "example": [ + "updateHookDefaultScheduledEnabled", + "updateHookDefaultScheduledInterval", + "updateHookDefaultScheduledIntervalLength", + "updateHookDefaultScheduledIntervalTime" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/authentication": { + "get": { + "operationId": "getOrganizationAuthenticationSettings", + "description": "Get authentication settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "subdomain": { + "type": "string" + }, + "loginSubdomain": { + "type": "string" + }, + "disableInvite": { + "type": "boolean" + }, + "saml": { + "type": "object", + "properties": { + "callbackUrl": { + "type": "string" + }, + "loginUrl": { + "type": "string" + }, + "audienceUrl": { + "type": "string" + }, + "id": { + "type": "number" + }, + "entryPoint": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "audience": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ldap": { + "type": "object", + "properties": { + "passwordIsSet": { + "type": "boolean" + }, + "id": { + "type": "number" + }, + "organizationId": { + "type": "number" + }, + "enabled": { + "type": "boolean" + }, + "server": { + "type": "string" + }, + "port": { + "type": "number" + }, + "ssl": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "searchBase": { + "type": "string" + }, + "searchFilter": { + "type": "string" + }, + "useGroups": { + "type": "boolean" + }, + "groupBase": { + "type": "string" + }, + "groupFilter": { + "type": "string" + }, + "groupNameAttr": { + "type": "string" + }, + "groupDNAttr": { + "type": "string" + }, + "userEmailAttr": { + "type": "string" + }, + "userNameAttr": { + "type": "string" + }, + "uidAttr": { + "type": "string" + }, + "allowEmptyEmail": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "sso": { + "type": "object", + "properties": { + "ldap": { + "type": "boolean" + }, + "saml": { + "type": "boolean" + }, + "google": { + "type": "boolean" + } + } + } + } + }, + "examples": { + "AuthenticationSettings": { + "value": { + "subdomain": "example-test", + "loginSubdomain": "http://example-test..io:9578", + "disableInvite": true, + "saml": { + "callbackUrl": "http://example-test..io:9578/account/saml/1/callback", + "loginUrl": "http://example-test..io:9578/account/saml/1", + "audienceUrl": "http://example-test..io:9578/account/saml/1/ae1a20f1-0d1f-4356-a0d3-67c335763906", + "id": 39, + "organizationId": 1, + "entryPoint": "12", + "cert": "12", + "audience": "ae1a20f1-0d1f-4356-a0d3-67c335763906", + "createdAt": "2024-01-25T00:21:19.744Z", + "updatedAt": "2024-01-25T00:21:19.744Z" + }, + "ldap": { + "passwordIsSet": true, + "id": 3, + "organizationId": 1, + "enabled": false, + "server": "ldap.example.com", + "port": 636, + "ssl": true, + "username": "ldap_user", + "searchBase": "ou=users,dc=example,dc=com", + "searchFilter": "(objectClass=person)", + "useGroups": false, + "groupBase": "groupBase", + "groupFilter": "groupFilter2", + "groupNameAttr": "groupNameAttr", + "groupDNAttr": "groupDNAttr", + "userEmailAttr": "email", + "userNameAttr": "cn", + "uidAttr": "uid", + "allowEmptyEmail": false, + "createdAt": "2024-01-10T18:36:41.911Z", + "updatedAt": "2024-01-12T00:25:33.867Z" + }, + "sso": { + "google": true, + "saml": true, + "ldap": true + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateOrganizationAuthenticationSettings", + "description": "Update authentication settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "subdomain": { + "type": "string" + }, + "disableInvite": { + "type": "boolean" + } + } + }, + "examples": { + "AuthenticationSettings": { + "value": { + "disableInvite": false, + "subdomain": "test" + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Settings Payload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/saml": { + "put": { + "operationId": "updateOrganizationSamlSettings", + "description": "Update SAML SSO settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "entryPoint", + "cert", + "audience" + ], + "properties": { + "entryPoint": { + "type": "string", + "description": "Identity Provider Single Sign On URL" + }, + "cert": { + "type": "string", + "description": "X.509 Certificate from the identity provider" + }, + "audience": { + "type": "string", + "description": "Audience URI / SP Entity ID" + }, + "orgRoleManagement": { + "type": "string", + "enum": [ + "fossa", + "idp", + "mixed" + ], + "description": "Whether Organization Roles should be managed by FOSSA, the Identity Provider, or both", + "default": "fossa" + }, + "teamRoleManagement": { + "type": "string", + "enum": [ + "fossa", + "idp_teams_fossa_roles", + "idp", + "mixed" + ], + "description": "Whether Teams and Team Roles should be managed by FOSSA, the Identity Provider, or both", + "default": "fossa" + }, + "createMissingTeams": { + "type": "boolean", + "description": "Whether to automatically create teams that are specified in SAML attributes but don't exist in the organization yet", + "default": true + } + } + }, + "examples": { + "SamlConfig": { + "value": { + "entryPoint": "https://sso.example.com/saml2/idp", + "cert": "-----BEGIN CERTIFICATE-----\nMIIFczCCA1ugAwIBAgIVANqq2WZ8FdYKSTIb0z2si06t2TnhMA0GCSqGSIb3DQEB\nCwUAMHMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEQMA4GA1UEBxMHQm91bGRl\n...\n-----END CERTIFICATE-----", + "audience": "http://localhost:9578/account/saml/1/6a817616-7f73-4381-96f5-01e35908ed80", + "orgRoleManagement": "mixed", + "teamRoleManagement": "idp_teams_fossa_roles", + "createMissingTeams": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "organizationId": { + "type": "integer" + }, + "entryPoint": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "audience": { + "type": "string" + }, + "orgRoleManagement": { + "type": "string", + "enum": [ + "fossa", + "idp", + "mixed" + ] + }, + "teamRoleManagement": { + "type": "string", + "enum": [ + "fossa", + "idp_teams_fossa_roles", + "idp", + "mixed" + ] + }, + "createMissingTeams": { + "type": "boolean" + }, + "callbackUrl": { + "type": "string" + }, + "loginUrl": { + "type": "string" + }, + "audienceUrl": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "examples": { + "SamlStrategy": { + "value": { + "id": 1, + "organizationId": 123, + "entryPoint": "https://sso.example.com/saml2/idp", + "cert": "-----BEGIN CERTIFICATE-----\nMIIFczCCA1ugAwIBAgIVANqq2WZ8FdYKSTIb0z2si06t2TnhMA0GCSqGSIb3DQEB\nCwUAMHMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEQMA4GA1UEBxMHQm91bGRl\n...\n-----END CERTIFICATE-----", + "audience": "6a817616-7f73-4381-96f5-01e35908ed80", + "orgRoleManagement": "mixed", + "teamRoleManagement": "idp_teams_fossa_roles", + "createMissingTeams": true, + "callbackUrl": "http://localhost:9578/account/saml/1/callback", + "loginUrl": "http://localhost:9578/account/saml/1", + "audienceUrl": "http://localhost:9578/account/saml/1/6a817616-7f73-4381-96f5-01e35908ed80", + "createdAt": "2025-11-06T19:00:00.000Z", + "updatedAt": "2025-11-06T19:00:00.000Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid Request": { + "value": { + "code": 1000, + "message": "You cannot configure SAML SSO because your organization already has Google SSO configured.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOrganizationSamlSettings", + "description": "Delete SAML SSO settings for an organization. This will remove the organization's SAML configuration and any associated organization domains using SAML authentication.", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK - SAML settings successfully deleted" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid organization ID": { + "value": { + "code": 1000, + "message": "Invalid organization ID parameter in request path.", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2005, + "message": "User does not have permission to view this resource", + "name": "ForbiddenError", + "httpStatusCode": 403 + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/pod": { + "get": { + "operationId": "getOrganizationCocoapodsSettings", + "description": "Get authentication settings for Cocoapods", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "ID of the Cocoapods source in the FOSSA DB" + }, + "organizationId": { + "type": "number", + "description": "Organization ID that owns this source" + }, + "url": { + "type": "string", + "description": "URL of the Cocoapods spec repo" + } + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "List of sources": { + "value": [ + { + "url": "www.specrepo1.com", + "organizationId": 123, + "id": 123 + }, + { + "url": "www.specrepo2.com", + "organizationId": 123, + "id": 124 + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationCocoapodsSettings", + "description": "Update authentication settings for Cocoapods. Payload accepts a list of strings representing spec repo URL's", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": [ + "www.specrepo1.com/specs", + "www.specrepo2.com/specs" + ] + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/bower": { + "get": { + "operationId": "getOrganizationBowerSettings", + "description": "Get authentication settings for Bower", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the config (For FOSSA internal usage)" + }, + "url": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasUrl": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing URL is obfuscated in the response" + } + } + }, + "description": "List of configured Bower registries" + }, + "useArtifactory": { + "type": "boolean", + "description": "Does this registry use Artifactory?" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Registries": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "hasUrl": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "hasUrl": true + } + ], + "useArtifactory": false + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationBowerSettings", + "description": "Update authentication settings for Bower", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the config (For FOSSA internal usage)" + }, + "url": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasUrl": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing URL is obfuscated in the response" + } + } + }, + "description": "List of configured Bower registries" + }, + "useArtifactory": { + "type": "boolean", + "description": "Does this registry use Artifactory?" + } + } + }, + "examples": { + "New Registry": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": { + "__type": "s", + "value": "www.existingPrivateBowerSite.com" + } + } + ], + "useArtifactory": true + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/gem": { + "get": { + "operationId": "getOrganizationRubyGemsSettings", + "description": "Get authentication settings for RubyGems", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the gem server (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "URL of the external gem server" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the gem server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Rubygem servers" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Source Repositories": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": "www.privategems.com/gems", + "username": "ruby_user", + "hasPassword": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationRubyGemsSettings", + "description": "Update authentication settings for RubyGems", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the gem server (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "URL of the external gem server" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the gem server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Rubygem servers" + } + } + }, + "examples": { + "New Source Repo": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": "www.privategems.com/gems", + "username": "ruby_user", + "password": { + "__type": "s", + "value": "gemSecretPassword" + } + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/mvn": { + "get": { + "operationId": "getOrganizationMavenSettings", + "description": "Get authentication settings for Maven", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven repo (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Server if credentials are necessary)" + }, + "url": { + "type": "string", + "description": "URL of the Maven Repository" + } + } + }, + "description": "List of configured Maven Repositories" + }, + "servers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven Server (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Repository)" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Maven repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Credentials for Maven Repositories" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Maven Repositories": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "id": "Maven Private Server", + "url": "www.privatemaven.com/mvn" + } + ], + "servers": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "id": "Maven Private Server", + "username": "mvn_user", + "hasPassword": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationMavenSettings", + "description": "Update authentication settings for Maven", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven repo (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Server if credentials are necessary)" + }, + "url": { + "type": "string", + "description": "URL of the Maven Repository" + } + } + }, + "description": "List of configured Maven Repositories" + }, + "servers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven Server (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Repository)" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Maven repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Credentials for Maven Repositories" + } + } + }, + "examples": { + "New Maven Repo": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "id": "Maven Private Server", + "url": "www.privatemaven.com/mvn" + } + ], + "servers": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "id": "Maven Private Server", + "username": "mvn_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/nuget": { + "get": { + "operationId": "getOrganizationNugetSettings", + "description": "Get authentication settings for Nuget", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Nuget Feed (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Nuget Feed" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Nuget Feed" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Nuget Feeds" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Nuget Repositories": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "username": "nuget_user", + "url": "www.nugetrepo.com/repo", + "hasPassword": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationNugetSettings", + "description": "Update authentication settings for Nuget", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Nuget Feed (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Nuget Feed" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Nuget Feed" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Nuget Feeds" + } + } + }, + "examples": { + "New Nuget Repo": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.nugetrepo.com/repo", + "username": "nuget_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/pip": { + "get": { + "operationId": "getOrganizationPipSettings", + "description": "Get authentication settings for Pip", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Pip repository (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Pip repository" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Pip repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Pip Repositories" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Pip Repositories": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "username": "pip_user", + "url": "www.piprepo.com/repo", + "hasPassword": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationPipSettings", + "description": "Update authentication settings for Pip", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Pip repository (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Pip repository" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Pip repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Pip Repositories" + } + } + }, + "examples": { + "New Pip Repo": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.piprepo.com/repo", + "username": "pip_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/git": { + "get": { + "operationId": "getOrganizationGitSettings", + "description": "Get authentication settings for Git", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "authOptions": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "oauth_key" + ], + "description": "FOSSA internal type" + }, + "value": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + } + } + }, + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "basic" + ], + "description": "FOSSA internal type" + }, + "username": { + "type": "string", + "description": "Username to authenticate to the remote Git server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + } + ] + }, + "description": "List of Git configurations" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "Git config": { + "value": { + "authOptions": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "token", + "type": "oauth_key", + "hasToken": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "user/pass", + "type": "basic", + "username": "git_user", + "hasPassword": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationGitSettings", + "description": "Update authentication settings for Git", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "authOptions": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "oauth_key" + ], + "description": "FOSSA internal type" + }, + "value": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + } + } + }, + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "basic" + ], + "description": "FOSSA internal type" + }, + "username": { + "type": "string", + "description": "Username to authenticate to the remote Git server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + } + ] + }, + "description": "List of Git configurations" + } + } + }, + "examples": { + "New Git Configs": { + "value": { + "authOptions": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "token", + "type": "oauth_key", + "value": { + "__type": "s", + "value": "123456789" + } + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "user/pass", + "type": "basic", + "username": "git_user", + "password": { + "__type": "s", + "value": "password" + } + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/languages/npm": { + "get": { + "operationId": "getOrganizationNPMSettings", + "description": "Get authentication settings for NPM", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "required": [ + "url" + ], + "oneOf": [ + { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "description": "UUID of the NPM registry (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the NPM registry" + }, + "auth": { + "type": "object", + "email": { + "type": "string", + "description": "Email associated to the NPM registry" + }, + "username": { + "type": "string", + "description": "Username associated to the NPM registry" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + }, + "token": { + "type": "string", + "description": "Token associated to the NPM registry" + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + }, + "alwaysAuth": { + "type": "boolean", + "readOnly": true, + "description": "True when at least one auth value is set. Internal field used in NPM API" + } + }, + "ca": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasCa": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing CA is obfuscated in the response" + } + } + }, + "description": "List of NPM configurations" + } + } + }, + { + "type": "null" + } + ] + }, + "examples": { + "NPM config": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth1", + "auth": { + "email": "foo@bar.com", + "username": "npm_user", + "hasPassword": true, + "hasToken": false, + "alwaysAuth": true + }, + "hasCa": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth2", + "auth": { + "hasToken": true, + "hasPassword": false + }, + "hasCa": true + } + ] + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationNPMSettings", + "description": "Update authentication settings for NPM", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "description": "UUID of the NPM registry (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the NPM registry" + }, + "auth": { + "type": "object", + "email": { + "type": "string", + "description": "Email associated to the NPM registry" + }, + "username": { + "type": "string", + "description": "Username associated to the NPM registry" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + }, + "token": { + "type": "string", + "description": "Token associated to the NPM registry" + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + }, + "alwaysAuth": { + "type": "boolean", + "readOnly": true, + "description": "True when at least one auth value is set. Internal field used in NPM API" + } + }, + "ca": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasCa": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing CA is obfuscated in the response" + } + } + }, + "description": "List of NPM configurations" + } + } + }, + "examples": { + "New NPM Configs": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth1", + "auth": { + "email": "foo@bar.com", + "username": "npm_user", + "password": { + "__type": "s", + "value": "password" + } + }, + "hasCa": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth2", + "auth": { + "token": { + "__type": "s", + "value": "2324234234" + } + }, + "hasCa": true + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No content" + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No Organization Found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/integrations/custom-license-scans": { + "get": { + "operationId": "getOrganizationCustomLicenseScanSettings", + "description": "Get custom license scan settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the custom license scan" + } + } + } + ] + } + }, + "examples": { + "Custom License Scan Settings": { + "value": [ + { + "id": 1, + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "putOrganizationCustomLicenseScanSettings", + "description": "Update custom license scan settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Organization ID", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the custom license scan" + } + } + } + ] + } + }, + "examples": { + "Custom License Scan Settings": { + "value": [ + { + "id": 1, + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + }, + { + "id": null, + "name": "Custom License", + "matchCriteria": "[Cc]ustom [Ll]icense" + } + ] + } + } + } + } + }, + "responses": { + "204": { + "description": "No content", + "content": { + "application/json": { + "example": "" + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/organizations/{id}/settings/integrations/slack": { + "get": { + "operationId": "getOrganizationSlackSettings", + "description": "Get Slack webhook settings for an organization", + "tags": [ + "Organization Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "channel": { + "description": "The Slack channel to send updates to", + "type": "string" + }, + "webhook_url": { + "description": "The configured webhook url in your Slack Application", + "type": "string" + } + } + } + }, + "examples": { + "Slack Settings": { + "value": [ + { + "channel": "#fossa-licensing-notifications", + "webhook_url": "https://hooks.slack.com/services/ABCD/EFG/HIJK/LMNOP" + }, + { + "channel": "#fossa-security-notifications", + "webhook_url": "https://hooks.slack.com/services/QRST/UBWX/YZ12/3456" + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + } + } + } + }, + "/jira/{id}": { + "delete": { + "operationId": "deleteJiraConfiguration", + "description": "Delete configuration settings for a specific Jira Site", + "tags": [ + "Jira Integration Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of the Jira site that was requested to be deleted" + }, + "deleted": { + "type": "boolean", + "description": "whether the Jira sire was successfully deleted or not" + } + } + }, + "examples": { + "Successful Delete": { + "value": { + "deleted": true, + "id": 1 + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of the Jira site that was requested to be deleted" + }, + "deleted": { + "type": "boolean", + "description": "whether the Jira sire was successfully deleted or not" + } + } + }, + "examples": { + "Failed Delete": { + "value": { + "deleted": false, + "id": 1 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + } + } + }, + "patch": { + "operationId": "patchJiraConfiguration", + "description": "Update config settings for a Jira site. Requires premium subscription.", + "tags": [ + "Jira Integration Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "organizationId": { + "type": "integer", + "readOnly": true + }, + "webhookURL": { + "type": "string", + "readOnly": true, + "description": "Used by the Jira to FOSSA Webhook" + }, + "createdAt": { + "type": "string", + "readOnly": true, + "description": "Timestamp when Jira was created" + }, + "enabled": { + "type": "boolean", + "description": "On/Off state of the Jira site enabled in FOSSA" + }, + "name": { + "type": "string", + "description": "Display name of your Jira site inside of FOSSA" + }, + "base_url": { + "type": [ + "string", + "null" + ], + "nullable": true, + "description": "Url of your Jira Site" + }, + "resolved_statuses": { + "type": "array", + "items": { + "type": "string", + "description": "An optional list of custom statuses to indicate a \"closed\" ticket. This is only used when resolvedStatusesEnabled is set to true" + } + }, + "resolvedStatusesEnabled": { + "type": "boolean", + "description": "When true, incoming webhooks will ignore/unignore issues linked to the specific tickets in question if the status matches one of the statuses listed in resolved_statuses." + }, + "credentials": { + "type": "object", + "properties": { + "basic": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "Jira username to authenticate to the site" + }, + "password": { + "type": "string", + "description": "Jira password to authenticate to the site (obfuscated when retrieved)" + } + } + } + } + }, + "headers": { + "type": [ + "object", + "null" + ], + "description": "HTTP headers to pass along when authenticating to the Jira site", + "additionalProperties": { + "type": "string" + } + }, + "issueTypes": { + "type": [ + "array", + "null" + ], + "description": "Available issue types to use when exporting tickets", + "items": { + "type": "string" + } + }, + "labels": { + "type": [ + "array", + "null" + ], + "description": "Available labels to include when exporting tickets. Corresponds to a label in Jira", + "items": { + "type": "string" + } + }, + "jiraProjectIds": { + "type": [ + "array", + "null" + ], + "description": "Available Jira Projects to export to from FOSSA", + "items": { + "type": "string" + } + }, + "customFields": { + "type": [ + "object", + "null" + ], + "description": "a dictionary of custom fields", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The corresponding Field ID in the Jira site for the given field" + }, + "displayName": { + "type": "string", + "description": "Display name to use in FOSSA" + }, + "isRequired": { + "type": "string", + "description": "On/off switch to tell FOSSA if the field is required when exporting tickets" + }, + "defaultValue": { + "description": "When provided, is the default value used when exporting a ticket", + "type": "string" + } + } + } + }, + "defaultLicensingProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting licensing issues" + }, + "defaultSecurityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting security issues" + }, + "defaultQualityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting quality issues" + }, + "defaultUniqueTickets": { + "description": "toggle to determine if each individual issue is 1:1 with a ticket upon creation", + "type": "boolean" + } + } + }, + "examples": { + "Update Base URL": { + "value": { + "base_url": "https://my-jira-site.com" + } + }, + "Update Enabled status": { + "value": { + "enabled": true + } + }, + "Update Credentials + Labels": { + "value": { + "credentials": { + "basic": { + "username": "jira_user", + "password": "password123" + } + }, + "labels": [ + "exported-from-fossa", + "licensing-issue" + ] + } + }, + "Update Headers and Custom Fields": { + "value": { + "headers": { + "x-token-test": "12345" + }, + "customFields": { + "12345": { + "fieldId": "12345", + "displayName": "Favorite soda", + "isRequired": false, + "defaultValue": "Sprite" + } + } + } + }, + "Update Components": { + "value": { + "components": [ + { + "id": "10001", + "displayName": "Component 1" + }, + { + "id": "10002", + "displayName": "Component 2" + } + ] + } + } + } + } + } + }, + "responses": { + "204": { + "description": "The resource was updated successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request (Malformed payload)": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error: expected undefined | null | string at root.base_url but found [4,5,6]", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "404": { + "description": "NotFound", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Not found": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Jira with ID 123 not found in org with ID 12345.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + } + } + } + } + } + } + } + }, + "/jira": { + "post": { + "operationId": "createJiraConfiguration", + "description": "Create new configuration settings for a Jira Site. Requires premium subscription.", + "tags": [ + "Jira Integration Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "organizationId": { + "type": "integer", + "readOnly": true + }, + "webhookURL": { + "type": "string", + "readOnly": true, + "description": "Used by the Jira to FOSSA Webhook" + }, + "createdAt": { + "type": "string", + "readOnly": true, + "description": "Timestamp when Jira was created" + }, + "enabled": { + "type": "boolean", + "description": "On/Off state of the Jira site enabled in FOSSA" + }, + "name": { + "type": "string", + "description": "Display name of your Jira site inside of FOSSA" + }, + "base_url": { + "type": [ + "string", + "null" + ], + "nullable": true, + "description": "Url of your Jira Site" + }, + "resolved_statuses": { + "type": "array", + "items": { + "type": "string", + "description": "An optional list of custom statuses to indicate a \"closed\" ticket. This is only used when resolvedStatusesEnabled is set to true" + } + }, + "resolvedStatusesEnabled": { + "type": "boolean", + "description": "When true, incoming webhooks will ignore/unignore issues linked to the specific tickets in question if the status matches one of the statuses listed in resolved_statuses." + }, + "credentials": { + "type": "object", + "properties": { + "basic": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "Jira username to authenticate to the site" + }, + "password": { + "type": "string", + "description": "Jira password to authenticate to the site (obfuscated when retrieved)" + } + } + } + } + }, + "headers": { + "type": [ + "object", + "null" + ], + "description": "HTTP headers to pass along when authenticating to the Jira site", + "additionalProperties": { + "type": "string" + } + }, + "issueTypes": { + "type": [ + "array", + "null" + ], + "description": "Available issue types to use when exporting tickets", + "items": { + "type": "string" + } + }, + "labels": { + "type": [ + "array", + "null" + ], + "description": "Available labels to include when exporting tickets. Corresponds to a label in Jira", + "items": { + "type": "string" + } + }, + "jiraProjectIds": { + "type": [ + "array", + "null" + ], + "description": "Available Jira Projects to export to from FOSSA", + "items": { + "type": "string" + } + }, + "customFields": { + "type": [ + "object", + "null" + ], + "description": "a dictionary of custom fields", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The corresponding Field ID in the Jira site for the given field" + }, + "displayName": { + "type": "string", + "description": "Display name to use in FOSSA" + }, + "isRequired": { + "type": "string", + "description": "On/off switch to tell FOSSA if the field is required when exporting tickets" + }, + "defaultValue": { + "description": "When provided, is the default value used when exporting a ticket", + "type": "string" + } + } + } + }, + "defaultLicensingProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting licensing issues" + }, + "defaultSecurityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting security issues" + }, + "defaultQualityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting quality issues" + }, + "defaultUniqueTickets": { + "description": "toggle to determine if each individual issue is 1:1 with a ticket upon creation", + "type": "boolean" + } + } + }, + "examples": { + "New Jira": { + "value": { + "name": "New Jira Site", + "enabled": true, + "base_url": "https://my-jira-site.com" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "organizationId": { + "type": "integer", + "readOnly": true + }, + "webhookURL": { + "type": "string", + "readOnly": true, + "description": "Used by the Jira to FOSSA Webhook" + }, + "createdAt": { + "type": "string", + "readOnly": true, + "description": "Timestamp when Jira was created" + }, + "enabled": { + "type": "boolean", + "description": "On/Off state of the Jira site enabled in FOSSA" + }, + "name": { + "type": "string", + "description": "Display name of your Jira site inside of FOSSA" + }, + "base_url": { + "type": [ + "string", + "null" + ], + "nullable": true, + "description": "Url of your Jira Site" + }, + "resolved_statuses": { + "type": "array", + "items": { + "type": "string", + "description": "An optional list of custom statuses to indicate a \"closed\" ticket. This is only used when resolvedStatusesEnabled is set to true" + } + }, + "resolvedStatusesEnabled": { + "type": "boolean", + "description": "When true, incoming webhooks will ignore/unignore issues linked to the specific tickets in question if the status matches one of the statuses listed in resolved_statuses." + }, + "credentials": { + "type": "object", + "properties": { + "basic": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "Jira username to authenticate to the site" + }, + "password": { + "type": "string", + "description": "Jira password to authenticate to the site (obfuscated when retrieved)" + } + } + } + } + }, + "headers": { + "type": [ + "object", + "null" + ], + "description": "HTTP headers to pass along when authenticating to the Jira site", + "additionalProperties": { + "type": "string" + } + }, + "issueTypes": { + "type": [ + "array", + "null" + ], + "description": "Available issue types to use when exporting tickets", + "items": { + "type": "string" + } + }, + "labels": { + "type": [ + "array", + "null" + ], + "description": "Available labels to include when exporting tickets. Corresponds to a label in Jira", + "items": { + "type": "string" + } + }, + "jiraProjectIds": { + "type": [ + "array", + "null" + ], + "description": "Available Jira Projects to export to from FOSSA", + "items": { + "type": "string" + } + }, + "customFields": { + "type": [ + "object", + "null" + ], + "description": "a dictionary of custom fields", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The corresponding Field ID in the Jira site for the given field" + }, + "displayName": { + "type": "string", + "description": "Display name to use in FOSSA" + }, + "isRequired": { + "type": "string", + "description": "On/off switch to tell FOSSA if the field is required when exporting tickets" + }, + "defaultValue": { + "description": "When provided, is the default value used when exporting a ticket", + "type": "string" + } + } + } + }, + "defaultLicensingProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting licensing issues" + }, + "defaultSecurityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting security issues" + }, + "defaultQualityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting quality issues" + }, + "defaultUniqueTickets": { + "description": "toggle to determine if each individual issue is 1:1 with a ticket upon creation", + "type": "boolean" + } + } + }, + "examples": { + "Successful Create": { + "value": { + "credentials": { + "basic": { + "username": "jira_user", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/00000000000/${issue.key}", + "id": 16, + "organizationId": 123, + "name": "Team 1 Jira site", + "base_url": "www.jira-site1.com", + "enabled": true, + "resolved_statuses": [ + "Done", + "Resolved", + "Closed" + ], + "resolvedStatusesEnabled": false, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "licensing-issue" + ], + "jiraProjectIds": [ + "PROD", + "STAG" + ], + "defaultLicensingProject": null, + "defaultSecurityProject": null, + "defaultQualityProject": null, + "createdAt": "2024-01-08T19:11:01.415Z" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad Request (Malformed payload)": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error: expected undefined | null | string at root.base_url but found [4,5,6]", + "name": "BadRequestError", + "httpStatusCode": 400 + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + } + } + } + } + } + } + }, + "get": { + "operationId": "getJiraConfigurations", + "description": "Get configuration settings for all Jira Sites in an organization", + "tags": [ + "Jira Integration Settings" + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "organizationId": { + "type": "integer", + "readOnly": true + }, + "webhookURL": { + "type": "string", + "readOnly": true, + "description": "Used by the Jira to FOSSA Webhook" + }, + "createdAt": { + "type": "string", + "readOnly": true, + "description": "Timestamp when Jira was created" + }, + "enabled": { + "type": "boolean", + "description": "On/Off state of the Jira site enabled in FOSSA" + }, + "name": { + "type": "string", + "description": "Display name of your Jira site inside of FOSSA" + }, + "base_url": { + "type": [ + "string", + "null" + ], + "nullable": true, + "description": "Url of your Jira Site" + }, + "resolved_statuses": { + "type": "array", + "items": { + "type": "string", + "description": "An optional list of custom statuses to indicate a \"closed\" ticket. This is only used when resolvedStatusesEnabled is set to true" + } + }, + "resolvedStatusesEnabled": { + "type": "boolean", + "description": "When true, incoming webhooks will ignore/unignore issues linked to the specific tickets in question if the status matches one of the statuses listed in resolved_statuses." + }, + "credentials": { + "type": "object", + "properties": { + "basic": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "Jira username to authenticate to the site" + }, + "password": { + "type": "string", + "description": "Jira password to authenticate to the site (obfuscated when retrieved)" + } + } + } + } + }, + "headers": { + "type": [ + "object", + "null" + ], + "description": "HTTP headers to pass along when authenticating to the Jira site", + "additionalProperties": { + "type": "string" + } + }, + "issueTypes": { + "type": [ + "array", + "null" + ], + "description": "Available issue types to use when exporting tickets", + "items": { + "type": "string" + } + }, + "labels": { + "type": [ + "array", + "null" + ], + "description": "Available labels to include when exporting tickets. Corresponds to a label in Jira", + "items": { + "type": "string" + } + }, + "jiraProjectIds": { + "type": [ + "array", + "null" + ], + "description": "Available Jira Projects to export to from FOSSA", + "items": { + "type": "string" + } + }, + "customFields": { + "type": [ + "object", + "null" + ], + "description": "a dictionary of custom fields", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The corresponding Field ID in the Jira site for the given field" + }, + "displayName": { + "type": "string", + "description": "Display name to use in FOSSA" + }, + "isRequired": { + "type": "string", + "description": "On/off switch to tell FOSSA if the field is required when exporting tickets" + }, + "defaultValue": { + "description": "When provided, is the default value used when exporting a ticket", + "type": "string" + } + } + } + }, + "defaultLicensingProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting licensing issues" + }, + "defaultSecurityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting security issues" + }, + "defaultQualityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting quality issues" + }, + "defaultUniqueTickets": { + "description": "toggle to determine if each individual issue is 1:1 with a ticket upon creation", + "type": "boolean" + } + } + } + }, + "examples": { + "Org with Multiple Jira Sites": { + "value": [ + { + "credentials": { + "basic": { + "username": "jira_user", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/00000000000/${issue.key}", + "id": 16, + "organizationId": 123, + "name": "Team 1 Jira site", + "base_url": "www.jira-site1.com", + "enabled": true, + "resolved_statuses": [ + "Done", + "Resolved", + "Closed" + ], + "resolvedStatusesEnabled": false, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "licensing-issue" + ], + "jiraProjectIds": [ + "PROD", + "STAG" + ], + "defaultLicensingProject": null, + "defaultSecurityProject": null, + "defaultQualityProject": null, + "createdAt": "2024-01-08T19:11:01.415Z" + }, + { + "credentials": { + "basic": { + "username": "jira_user2", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/0000000000000/${issue.key}", + "id": 24, + "organizationId": 123, + "name": "Team 2 Jira site", + "base_url": "www.jira-site2.com", + "enabled": false, + "resolved_statuses": [ + "CustomDone" + ], + "resolvedStatusesEnabled": true, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "security-issue" + ], + "jiraProjectIds": [ + "PROD", + "TEST", + "DEV" + ], + "defaultLicensingProject": "PROD", + "defaultSecurityProject": "TEST", + "defaultQualityProject": "DEV", + "createdAt": "2024-01-08T19:11:01.415Z" + } + ] + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Bad API Token": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "examples": { + "Forbidden": { + "value": { + "message": "Forbidden" + } + } + } + } + } + } + } + } + }, + "/audit_logs": { + "get": { + "operationId": "getAuditLogs", + "description": "Retrieves a list of audit logs.", + "tags": [ + "Audit Logs" + ], + "parameters": [ + { + "name": "offset", + "description": "The number of records to skip", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "limit", + "description": "The number of records to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sortBy", + "description": "The field to sort by (defaults to createdAt)", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "id", + "actingUserId", + "actingUserEmail", + "actingUserName", + "actingUserRole", + "organizationId", + "userId", + "teamId", + "buildId", + "dependencyId", + "licenseId", + "policyId", + "projectId", + "ruleId", + "locator", + "revisionLicenseId", + "issueId", + "action", + "topic", + "name", + "old_value", + "new_value", + "description", + "createdAt" + ] + } + }, + { + "name": "sortDir", + "description": "The direction to sort by (defaults to DESC)", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + } + }, + { + "name": "startDate", + "description": "The start date to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endDate", + "description": "The end date to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "actingUserIds[]", + "description": "The acting user IDs to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "actions[]", + "description": "The actions to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "topics[]", + "description": "The topics to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "topicActions[]", + "description": "The topic actions to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "startingAfter", + "description": "The id to start after to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endingBefore", + "description": "The id to end before to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Audit log list", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier for the audit log." + }, + "actingUserId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the user who performed the action." + }, + "actingUserEmail": { + "type": [ + "string", + "null" + ], + "description": "The email address of the user who performed the action." + }, + "actingUserName": { + "type": [ + "string", + "null" + ], + "description": "The name of the user who performed the action." + }, + "actingUserRole": { + "type": [ + "string", + "null" + ], + "description": "The role of the user who performed the action." + }, + "organizationId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the organization." + }, + "userId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the user." + }, + "teamId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the team." + }, + "buildId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the build." + }, + "dependencyId": { + "type": [ + "string", + "null" + ], + "description": "The unique identifier for the dependency." + }, + "licenseId": { + "type": [ + "string", + "null" + ], + "description": "The unique identifier for the license." + }, + "policyId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the policy." + }, + "projectId": { + "type": [ + "string", + "null" + ], + "description": "The unique identifier for the project." + }, + "ruleId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the rule." + }, + "locator": { + "type": [ + "string", + "null" + ], + "description": "The locator for the dependency." + }, + "revisionLicenseId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the revision license." + }, + "issueId": { + "type": [ + "integer", + "null" + ], + "description": "The unique identifier for the issue." + }, + "action": { + "type": "string", + "description": "The action that was performed." + }, + "topic": { + "type": "string", + "description": "The topic of the action." + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "The name of the action." + }, + "old_value": { + "type": [ + "string", + "null" + ], + "description": "The old value before the change." + }, + "new_value": { + "type": [ + "string", + "null" + ], + "description": "The new value after the change." + }, + "description": { + "type": [ + "string", + "null" + ], + "description": "The description of the action." + }, + "createdAt": { + "type": "string", + "description": "The date and time the action was performed." + } + } + } + }, + "examples": { + "Audit logs": { + "value": [ + { + "id": 123, + "actingUserId": 123, + "actingUserEmail": "user@fossa.com", + "actingUserName": "user@fossa.com", + "actingUserRole": "project.create", + "organizationId": 123, + "userId": null, + "teamId": null, + "buildId": null, + "dependencyId": null, + "licenseId": null, + "policyId": null, + "projectId": null, + "ruleId": null, + "locator": null, + "revisionLicenseId": null, + "issueId": null, + "action": "ADD_PROJECT", + "topic": "Project", + "name": null, + "old_value": null, + "new_value": null, + "description": "Imported project \"github.com/foo/bar\" via github", + "createdAt": "2024-05-13T16:42:54.067Z" + } + ] + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "string" + }, + "examples": { + "No permission to view": { + "value": "Forbidden" + }, + "Org not permissioned": { + "value": "User not permissioned for feature. Feature requires premium subscription access level." + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/audit_logs/export": { + "post": { + "operationId": "getAuditLogsExport", + "description": "Request an export of audit logs. The export will be generated asynchronously and a link to download the CSV file will be emailed to you.", + "tags": [ + "Audit Logs" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "startDate", + "endDate" + ], + "properties": { + "startDate": { + "type": "string", + "format": "date", + "description": "Filter audit logs to those created on or after this date (YYYY-MM-DD format)" + }, + "endDate": { + "type": "string", + "format": "date", + "description": "Filter audit logs to those created on or before this date (YYYY-MM-DD format)" + }, + "actingUserIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter audit logs to those created by the given user IDs" + }, + "actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter audit logs to those with the given actions" + }, + "topics": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter audit logs to those with the given topics" + }, + "topicActions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter audit logs to those with the given topic and action" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "201": { + "description": "The export task was created successfully. When the job is complete, you will receive an email with a link to download the CSV file.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "task": { + "type": "object", + "properties": { + "task": { + "type": "string", + "description": "Identifier for the task" + }, + "jobToken": { + "type": "string", + "description": "Token used to track the export job" + } + } + }, + "target": { + "type": "string", + "description": "Email address where the export link will be sent" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Invalid dates": { + "value": { + "message": "startDate and endDate must be valid dates" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "No permission": { + "value": { + "message": "Forbidden" + } + }, + "Subscription required": { + "value": { + "message": "User not permissioned for feature. Feature requires premium subscription access level." + } + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/count/audit_logs": { + "get": { + "operationId": "getAuditLogsCount", + "description": "Retrieves a count of audit logs.", + "tags": [ + "Audit Logs" + ], + "parameters": [ + { + "name": "offset", + "description": "The number of records to skip", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "limit", + "description": "The number of records to return", + "required": false, + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sortBy", + "description": "The field to sort by (defaults to createdAt)", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "id", + "actingUserId", + "actingUserEmail", + "actingUserName", + "actingUserRole", + "organizationId", + "userId", + "teamId", + "buildId", + "dependencyId", + "licenseId", + "policyId", + "projectId", + "ruleId", + "locator", + "revisionLicenseId", + "issueId", + "action", + "topic", + "name", + "old_value", + "new_value", + "description", + "createdAt" + ] + } + }, + { + "name": "sortDir", + "description": "The direction to sort by (defaults to DESC)", + "required": false, + "in": "query", + "schema": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + } + }, + { + "name": "startDate", + "description": "The start date to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endDate", + "description": "The end date to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "actingUserIds[]", + "description": "The acting user IDs to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "actions[]", + "description": "The actions to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "topics[]", + "description": "The topics to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "topicActions[]", + "description": "The topic actions to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "startingAfter", + "description": "The id to start after to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endingBefore", + "description": "The id to end before to filter audit logs to", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Audit log count", + "content": { + "application/json": { + "schema": { + "type": "integer" + }, + "examples": { + "audit_log_count": { + "value": 12 + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "string" + }, + "examples": { + "No permission to view": { + "value": "Forbidden" + }, + "Org not permissioned": { + "value": "User not permissioned for feature. Feature requires premium subscription access level." + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/components/signed_url": { + "get": { + "operationId": "getSignedUrl", + "description": "Get a signed URL for uploading component files to FOSSA, to expire in 5 minutes' time. Only SBOM imports are supported for non-premium accounts.", + "tags": [ + "Components" + ], + "parameters": [ + { + "in": "query", + "name": "packageSpec", + "schema": { + "type": "string" + }, + "description": "the package spec", + "required": true + }, + { + "in": "query", + "name": "revision", + "schema": { + "type": "string" + }, + "description": "The branch or revision of the component project being built.", + "required": true + }, + { + "in": "query", + "name": "fileType", + "schema": { + "type": "string", + "enum": [ + "archive", + "sbom" + ] + }, + "description": "The kind of file to be uploaded to the signed URL. If 'archive', the signed URL is for uplaoding a directory of source code. If 'sbom', the signed URL is for uploading an SBOM file (CycloneDX or SPDX).\n" + } + ], + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "200": { + "description": "Signed URL", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "signedUrl": { + "type": "string" + } + } + }, + "examples": { + "signedUrl": { + "value": "http://example.com/api/blob-storage?signature=80070713463e7749b90c2dc24911e275" + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "string" + }, + "examples": { + "No package spec": { + "value": "package spec not defined" + }, + "No revision": { + "value": "revision not defined" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "string" + }, + "examples": { + "No permission to view": { + "value": "Forbidden" + }, + "Org not permissioned": { + "value": "User not permissioned for feature. Feature requires premium subscription access level." + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "FossaApiError" + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + }, + "/components/build": { + "post": { + "operationId": "build", + "description": "Upload a component and start asynchronously building it. Only SBOM imports are supported for non-premium accounts.", + "tags": [ + "Components" + ], + "parameters": [ + { + "in": "query", + "name": "packageSpec", + "schema": { + "type": "string" + }, + "required": true, + "description": "The unresolved spec (i.e. a URL) that can be passed to a fetcher and resolved to a package id. For example:, underscore (npm), https://github.com/fossas/fossa (git), nokogiri (gem),\n" + }, + { + "in": "query", + "name": "revision", + "schema": { + "type": "string" + }, + "required": true, + "description": "The branch or revision of the component project being built." + }, + { + "in": "query", + "name": "dependency", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "" + }, + { + "in": "query", + "name": "description", + "schema": { + "type": "string" + }, + "description": "The project description for the archive" + }, + { + "in": "query", + "name": "fileType", + "schema": { + "type": "string", + "enum": [ + "archive", + "sbom" + ] + }, + "required": false, + "description": "The kind of component file to be built., If 'archive', the signed URL is for uplaoding a directory of source code., If 'sbom', the signed URL is for uploading an SBOM file (CycloneDX or SPDX).,\n" + }, + { + "in": "query", + "name": "branch", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "jiraProjectKey", + "schema": { + "type": "string" + }, + "description": "The corresponding Jira project for this component", + "required": false + }, + { + "in": "query", + "name": "link", + "schema": { + "type": "string" + }, + "description": "A link to attach to this revision", + "required": false + }, + { + "in": "query", + "name": "projectURL", + "schema": { + "type": "string" + }, + "description": "The URL of the project being uploaded", + "required": false + }, + { + "in": "query", + "name": "policy", + "schema": { + "type": "string" + }, + "description": "The name of the policy for this build.", + "required": false + }, + { + "in": "query", + "name": "policyId", + "schema": { + "type": "number" + }, + "description": "The ID of the policy for this build.", + "required": false + }, + { + "in": "query", + "name": "team", + "schema": { + "type": "string" + }, + "description": "The name of the team connected to the project.", + "required": false + }, + { + "in": "query", + "name": "title", + "schema": { + "type": "string" + }, + "description": "The title of the component.", + "required": false + }, + { + "in": "query", + "name": "releaseGroup", + "schema": { + "type": "string" + }, + "description": "The title of release group to add the project to.", + "required": false + }, + { + "in": "query", + "name": "releaseGroupRelease", + "schema": { + "type": "string" + }, + "description": "The title of release to add the project to.", + "required": false + }, + { + "in": "query", + "name": "labels", + "style": "form", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "required": false, + "description": "Set of labels to apply to a project. If the org or the project have too many labels, then the labels will be applied in order until limits are hit.\n" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "archives": { + "type": "object", + "required": true, + "description": "File upload metadata", + "properties": { + "packageSpec": { + "required": true, + "description": "The unresolved spec (i.e. a URL) that can be passed to a fetcher and resolved to a package id. For example:\nunderscore (npm)\nhttps://github.com/fossas/fossa (git)\nnokogiri (gem)\n", + "type": "string" + }, + "revision": { + "required": true, + "description": "The branch or revision of the component being uploaded.", + "type": "string" + }, + "description": { + "required": false, + "description": "The description of the archive.", + "type": "string" + }, + "projectURL": { + "required": false, + "description": "The homepage of the archive.", + "type": "string" + } + } + }, + "selectedTeams": { + "required": false, + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "A team ID", + "properties": { + "id": { + "type": "integer" + } + } + }, + { + "type": "object", + "description": "A team name", + "properties": { + "name": { + "type": "string" + } + } + } + ] + } + }, + "forceRebuild": { + "type": "boolean", + "required": false, + "description": "Force a rebuild no matter what" + } + } + } + } + } + }, + "security": [ + { + "ApiToken": [] + } + ], + "responses": { + "201": { + "description": "Created" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "type": "FossaForbiddenError" + }, + "examples": { + "No permission to view": { + "value": "Forbidden" + }, + "Org not permissioned": { + "value": "User not permissioned for feature. Feature requires premium subscription access level." + } + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "type": "FossaApiError" + }, + "examples": { + "Server Error": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2009, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "name": "InternalServerError", + "httpStatusCode": 500 + } + } + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "ApiToken": { + "type": "http", + "scheme": "bearer", + "description": "Enter the api token with the `Bearer: ` prefix, e.g. \"Bearer 123456\"" + } + }, + "parameters": { + "PaginationPage": { + "name": "page", + "description": "The specific page of data to return", + "in": "query", + "schema": { + "type": "integer", + "minimum": 1, + "default": 1 + } + }, + "ProjectTeamId": { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned projects.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + "ReleaseGroupTeamId": { + "name": "teamId", + "in": "query", + "description": "Filter by one or more team IDs. Providing \"null\" will return all unassigned release groups.", + "schema": { + "nullable": true, + "oneOf": [ + { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + ] + } + }, + "IssueOverviewStartDate": { + "name": "start", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to 30 days before the end date.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "IssueOverviewEndDate": { + "name": "end", + "in": "query", + "description": "The start date to pull Issue Overview data for. Defaults to the current date and time.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "IssueOverviewLabels": { + "name": "labels[]", + "in": "query", + "description": "The project labels to filter Issue Overview data to.", + "schema": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + } + }, + "IssueOverviewCategory": { + "name": "category", + "description": "The issue category to filter Issue Overview data to. If no category is chosen, it will fetch data for all issue categories.", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "licensing", + "vulnerability", + "quality" + ] + } + }, + "IssueOverviewProjectId": { + "name": "projectId", + "description": "The specific project ID to filter Issue Overview data to.", + "in": "query", + "schema": { + "type": "string" + } + } + }, + "schemas": { + "Locator": { + "type": "string", + "description": "FOSSA's identifier for a unique component" + }, + "Label": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of this label" + }, + "organizationId": { + "type": "integer", + "description": "ID of the organization that this Label is associated with" + }, + "label": { + "type": "string", + "description": "Text that this Label represents" + }, + "projects": { + "type": "array", + "items": { + "type": "string", + "description": "FOSSA's identifier for a unique component" + } + } + } + }, + "CustomLicenseScanConfig": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + "CustomLicenseScanConfigWithId": { + "allOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the custom license scan" + } + } + } + ] + }, + "CveWithDetails": { + "type": "object", + "properties": { + "cve": { + "type": "string", + "description": "CVE identifier (e.g., CVE-2021-44228)", + "pattern": "^CVE-\\d{4}-\\d{4,}$", + "example": "CVE-2021-44228" + }, + "description": { + "type": "string", + "nullable": true, + "description": "Detailed description of the vulnerability", + "example": "Apache Log4j2 2.0-beta9 through 2.15.0 JNDI features used in configuration do not protect against attacker controlled LDAP endpoints." + } + }, + "required": [ + "cve" + ] + }, + "SafeVersion": { + "type": "string" + }, + "SafeVersionDistance": { + "type": "string", + "enum": [ + "MAJOR", + "MINOR", + "PATCH" + ] + }, + "FossaForbiddenError": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message describing the error" + } + } + }, + "FossaApiError": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier associated with the error" + }, + "code": { + "type": "integer", + "description": "fossa specific error code" + }, + "message": { + "type": "string", + "description": "message associated with this error" + }, + "name": { + "type": "string", + "description": "name of the error" + }, + "httpStatusCode": { + "type": "integer", + "description": "http status code number" + } + } + }, + "GeneralOrganizationSettings": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "label": { + "type": "string" + }, + "projectCount": { + "type": "integer" + } + } + } + }, + "title": { + "type": "string" + }, + "email": { + "type": "string" + }, + "defaultRoleId": { + "type": "integer" + }, + "dependencySignatures": { + "type": "string" + }, + "disableNonCustomTeamUserRoles": { + "type": "boolean" + } + } + }, + "EditingGeneralOrganizationSettings": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, + "title": { + "type": "string" + }, + "email": { + "type": "string" + }, + "defaultRoleId": { + "type": "integer" + }, + "dependencySignatures": { + "type": "string" + }, + "disableNonCustomTeamUserRoles": { + "type": "boolean" + } + } + }, + "PrivacySettings": { + "type": "object", + "properties": { + "defaultProjectPrivacy": { + "description": "the default privacy setting for new projects", + "type": "string", + "enum": [ + "public", + "private" + ], + "nullable": true + } + } + }, + "GithubStatusCheckSettings": { + "type": "object", + "properties": { + "projectDefaultAutomatedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultProvidedIntegrationhookTimeout": { + "type": "number" + }, + "projectDefaultIntegrationhookFailState": { + "type": "string", + "enum": [ + "ERROR", + "SUCCESS" + ] + } + } + }, + "LicensingIssueSettings": { + "type": "object", + "properties": { + "defaultPolicyId": { + "type": "integer" + }, + "projectDefaultLicensingIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultLicensingStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterLicensing": { + "type": "integer" + }, + "projectDefaultSnippetLicensingIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet licensing issue scanning by default for projects in the organization" + } + } + }, + "SecurityIssueSettings": { + "type": "object", + "properties": { + "defaultSecurityPolicyId": { + "type": "integer" + }, + "projectDefaultSecurityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultSecurityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterVulnerability": { + "type": "integer" + }, + "projectDefaultSnippetSecurityIssueScanningEnabled": { + "type": "boolean", + "description": "Enable or disable snippet security issue scanning by default for projects in the organization" + } + } + }, + "QualityIssueSettings": { + "type": "object", + "properties": { + "defaultQualityPolicyId": { + "type": "integer" + }, + "projectDefaultQualityIssueScanningEnabled": { + "type": "boolean" + }, + "projectDefaultQualityStatusCheckEnabled": { + "type": "boolean" + }, + "projectDefaultStatusCheckFilterQuality": { + "type": "integer" + } + } + }, + "ContainerIssueSettings": { + "type": "object", + "properties": { + "projectDefaultExcludeBaseLayerIssuesLicensing": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesSecurity": { + "type": "boolean" + }, + "projectDefaultExcludeBaseLayerIssuesQuality": { + "type": "boolean" + } + } + }, + "NotificationsSettings": { + "type": "object", + "properties": { + "notificationDefaultEnabled": { + "type": "boolean", + "description": "the on/off status of project notifications" + }, + "notificationDefaultSlackScan": { + "type": "boolean", + "description": "the on/off status of slack notifications for scans" + }, + "notificationDefaultEmailScanUsers": { + "type": "array", + "items": { + "type": "number", + "description": "the list of user ids to email for scan notifications" + } + }, + "notificationDefaultEmailScanUserType": { + "type": "string", + "description": "The type of users to email for scan notifications. Each option represents a different set of users:\n- current: Only the current user will receive scan notifications.\n- all: All users will receive scan notifications.\n- custom: Custom set of users will receive scan notifications.\n", + "enum": [ + "current", + "all", + "custom" + ] + } + } + }, + "ProjectUpdateHooksSettings": { + "type": "object", + "properties": { + "updateHookDefaultScheduledEnabled": { + "type": "boolean", + "description": "the on/off status of if the update hook is enabled" + }, + "updateHookDefaultScheduledInterval": { + "type": "string", + "enum": [ + "hour", + "day", + "week" + ], + "nullable": true, + "description": "the cadence of the updates" + }, + "updateHookDefaultScheduledIntervalLength": { + "type": "integer", + "nullable": true, + "description": "the cadence of the scheduled updates" + }, + "updateHookDefaultScheduledIntervalTime": { + "type": "string", + "nullable": true, + "description": "date/time for the schedule update hook intervals" + } + } + }, + "AuthenticationSettings": { + "type": "object", + "properties": { + "subdomain": { + "type": "string" + }, + "loginSubdomain": { + "type": "string" + }, + "disableInvite": { + "type": "boolean" + }, + "saml": { + "type": "object", + "properties": { + "callbackUrl": { + "type": "string" + }, + "loginUrl": { + "type": "string" + }, + "audienceUrl": { + "type": "string" + }, + "id": { + "type": "number" + }, + "entryPoint": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "audience": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ldap": { + "type": "object", + "properties": { + "passwordIsSet": { + "type": "boolean" + }, + "id": { + "type": "number" + }, + "organizationId": { + "type": "number" + }, + "enabled": { + "type": "boolean" + }, + "server": { + "type": "string" + }, + "port": { + "type": "number" + }, + "ssl": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "searchBase": { + "type": "string" + }, + "searchFilter": { + "type": "string" + }, + "useGroups": { + "type": "boolean" + }, + "groupBase": { + "type": "string" + }, + "groupFilter": { + "type": "string" + }, + "groupNameAttr": { + "type": "string" + }, + "groupDNAttr": { + "type": "string" + }, + "userEmailAttr": { + "type": "string" + }, + "userNameAttr": { + "type": "string" + }, + "uidAttr": { + "type": "string" + }, + "allowEmptyEmail": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "sso": { + "type": "object", + "properties": { + "ldap": { + "type": "boolean" + }, + "saml": { + "type": "boolean" + }, + "google": { + "type": "boolean" + } + } + } + } + }, + "CustomLicenseScanSettings": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "custom license scan name" + }, + "matchCriteria": { + "type": "string", + "description": "regular expression for the custom license scan" + } + } + }, + { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the custom license scan" + } + } + } + ] + } + }, + "SlackWebhook": { + "type": "object", + "properties": { + "channel": { + "description": "The Slack channel to send updates to", + "type": "string" + }, + "webhook_url": { + "description": "The configured webhook url in your Slack Application", + "type": "string" + } + } + }, + "SlackSettings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "channel": { + "description": "The Slack channel to send updates to", + "type": "string" + }, + "webhook_url": { + "description": "The configured webhook url in your Slack Application", + "type": "string" + } + } + } + }, + "UpdateAuthenticationSettings": { + "type": "object", + "properties": { + "subdomain": { + "type": "string" + }, + "disableInvite": { + "type": "boolean" + } + } + }, + "DeletedJira": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "ID of the Jira site that was requested to be deleted" + }, + "deleted": { + "type": "boolean", + "description": "whether the Jira sire was successfully deleted or not" + } + } + }, + "Jira": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "organizationId": { + "type": "integer", + "readOnly": true + }, + "webhookURL": { + "type": "string", + "readOnly": true, + "description": "Used by the Jira to FOSSA Webhook" + }, + "createdAt": { + "type": "string", + "readOnly": true, + "description": "Timestamp when Jira was created" + }, + "enabled": { + "type": "boolean", + "description": "On/Off state of the Jira site enabled in FOSSA" + }, + "name": { + "type": "string", + "description": "Display name of your Jira site inside of FOSSA" + }, + "base_url": { + "type": [ + "string", + "null" + ], + "nullable": true, + "description": "Url of your Jira Site" + }, + "resolved_statuses": { + "type": "array", + "items": { + "type": "string", + "description": "An optional list of custom statuses to indicate a \"closed\" ticket. This is only used when resolvedStatusesEnabled is set to true" + } + }, + "resolvedStatusesEnabled": { + "type": "boolean", + "description": "When true, incoming webhooks will ignore/unignore issues linked to the specific tickets in question if the status matches one of the statuses listed in resolved_statuses." + }, + "credentials": { + "type": "object", + "properties": { + "basic": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "Jira username to authenticate to the site" + }, + "password": { + "type": "string", + "description": "Jira password to authenticate to the site (obfuscated when retrieved)" + } + } + } + } + }, + "headers": { + "type": [ + "object", + "null" + ], + "description": "HTTP headers to pass along when authenticating to the Jira site", + "additionalProperties": { + "type": "string" + } + }, + "issueTypes": { + "type": [ + "array", + "null" + ], + "description": "Available issue types to use when exporting tickets", + "items": { + "type": "string" + } + }, + "labels": { + "type": [ + "array", + "null" + ], + "description": "Available labels to include when exporting tickets. Corresponds to a label in Jira", + "items": { + "type": "string" + } + }, + "jiraProjectIds": { + "type": [ + "array", + "null" + ], + "description": "Available Jira Projects to export to from FOSSA", + "items": { + "type": "string" + } + }, + "customFields": { + "type": [ + "object", + "null" + ], + "description": "a dictionary of custom fields", + "additionalProperties": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "description": "The corresponding Field ID in the Jira site for the given field" + }, + "displayName": { + "type": "string", + "description": "Display name to use in FOSSA" + }, + "isRequired": { + "type": "string", + "description": "On/off switch to tell FOSSA if the field is required when exporting tickets" + }, + "defaultValue": { + "description": "When provided, is the default value used when exporting a ticket", + "type": "string" + } + } + } + }, + "defaultLicensingProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting licensing issues" + }, + "defaultSecurityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting security issues" + }, + "defaultQualityProject": { + "type": [ + "string", + "null" + ], + "description": "The Jira Project to default to when exporting quality issues" + }, + "defaultUniqueTickets": { + "description": "toggle to determine if each individual issue is 1:1 with a ticket upon creation", + "type": "boolean" + } + } + }, + "CocoapodsSource": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "ID of the Cocoapods source in the FOSSA DB" + }, + "organizationId": { + "type": "number", + "description": "Organization ID that owns this source" + }, + "url": { + "type": "string", + "description": "URL of the Cocoapods spec repo" + } + } + }, + "FetcherConfigSecret": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "BowerRegistry": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the config (For FOSSA internal usage)" + }, + "url": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasUrl": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing URL is obfuscated in the response" + } + } + }, + "BowerConfig": { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the config (For FOSSA internal usage)" + }, + "url": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasUrl": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing URL is obfuscated in the response" + } + } + }, + "description": "List of configured Bower registries" + }, + "useArtifactory": { + "type": "boolean", + "description": "Does this registry use Artifactory?" + } + } + }, + "GemServer": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the gem server (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "URL of the external gem server" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the gem server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "GemConfig": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the gem server (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "URL of the external gem server" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the gem server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Rubygem servers" + } + } + }, + "MavenRepository": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven repo (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Server if credentials are necessary)" + }, + "url": { + "type": "string", + "description": "URL of the Maven Repository" + } + } + }, + "MavenServer": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven Server (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Repository)" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Maven repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "MavenConfig": { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven repo (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Server if credentials are necessary)" + }, + "url": { + "type": "string", + "description": "URL of the Maven Repository" + } + } + }, + "description": "List of configured Maven Repositories" + }, + "servers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Maven Server (For FOSSA internal usage)" + }, + "id": { + "type": "string", + "description": "User configured ID (corresponds with a Maven Repository)" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Maven repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Credentials for Maven Repositories" + } + } + }, + "NugetRepository": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Nuget Feed (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Nuget Feed" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Nuget Feed" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "NugetConfig": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Nuget Feed (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Nuget Feed" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Nuget Feed" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Nuget Feeds" + } + } + }, + "PipRepository": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Pip repository (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Pip repository" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Pip repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "PipConfig": { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Pip repository (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the Pip repository" + }, + "username": { + "type": "string", + "description": "Username for authenticating to the Pip repository" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "description": "List of configured Pip Repositories" + } + } + }, + "GitTokenAuth": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "oauth_key" + ], + "description": "FOSSA internal type" + }, + "value": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + } + } + }, + "GitUserPasswordAuth": { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "basic" + ], + "description": "FOSSA internal type" + }, + "username": { + "type": "string", + "description": "Username to authenticate to the remote Git server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + }, + "GitAuth": { + "oneOf": [ + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "oauth_key" + ], + "description": "FOSSA internal type" + }, + "value": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + } + } + }, + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "basic" + ], + "description": "FOSSA internal type" + }, + "username": { + "type": "string", + "description": "Username to authenticate to the remote Git server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + } + ] + }, + "GitConfig": { + "type": "object", + "properties": { + "authOptions": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "oauth_key" + ], + "description": "FOSSA internal type" + }, + "value": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + } + } + }, + { + "type": "object", + "properties": { + "_id": { + "type": "number", + "description": "UUID of the Git Server (For FOSSA internal usage)" + }, + "displayName": { + "type": "string", + "description": "Display name of the Git token in FOSSA" + }, + "type": { + "type": "string", + "enum": [ + "basic" + ], + "description": "FOSSA internal type" + }, + "username": { + "type": "string", + "description": "Username to authenticate to the remote Git server" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + } + } + } + ] + }, + "description": "List of Git configurations" + } + } + }, + "NPMRegistryAuth": { + "type": "object", + "email": { + "type": "string", + "description": "Email associated to the NPM registry" + }, + "username": { + "type": "string", + "description": "Username associated to the NPM registry" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + }, + "token": { + "type": "string", + "description": "Token associated to the NPM registry" + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + }, + "alwaysAuth": { + "type": "boolean", + "readOnly": true, + "description": "True when at least one auth value is set. Internal field used in NPM API" + } + }, + "NPMRegistry": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "description": "UUID of the NPM registry (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the NPM registry" + }, + "auth": { + "type": "object", + "email": { + "type": "string", + "description": "Email associated to the NPM registry" + }, + "username": { + "type": "string", + "description": "Username associated to the NPM registry" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + }, + "token": { + "type": "string", + "description": "Token associated to the NPM registry" + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + }, + "alwaysAuth": { + "type": "boolean", + "readOnly": true, + "description": "True when at least one auth value is set. Internal field used in NPM API" + } + }, + "ca": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasCa": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing CA is obfuscated in the response" + } + } + }, + "NPMConfig": { + "type": "object", + "properties": { + "registries": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "description": "UUID of the NPM registry (For FOSSA internal usage)" + }, + "url": { + "type": "string", + "description": "Remote URL of the NPM registry" + }, + "auth": { + "type": "object", + "email": { + "type": "string", + "description": "Email associated to the NPM registry" + }, + "username": { + "type": "string", + "description": "Username associated to the NPM registry" + }, + "password": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasPassword": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing password is obfuscated in the response" + }, + "token": { + "type": "string", + "description": "Token associated to the NPM registry" + }, + "hasToken": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing token is obfuscated in the response" + }, + "alwaysAuth": { + "type": "boolean", + "readOnly": true, + "description": "True when at least one auth value is set. Internal field used in NPM API" + } + }, + "ca": { + "type": "object", + "properties": { + "__type": { + "type": "string", + "enum": [ + "s" + ] + }, + "value": { + "type": "string" + } + } + }, + "hasCa": { + "type": "boolean", + "readOnly": true, + "description": "Used when an existing CA is obfuscated in the response" + } + } + }, + "description": "List of NPM configurations" + } + } + }, + "SourcedLicense": { + "type": "object", + "properties": { + "depth": { + "type": "integer", + "example": 1 + }, + "licenseId": { + "type": "string", + "example": "MIT" + }, + "name": { + "type": "string", + "example": "MIT License" + }, + "matches": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ] + }, + "sources": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + }, + "example": { + "value": { + "depth": 1, + "licenseId": "MIT", + "name": "MIT License", + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + } + }, + "Obligation": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "The description of the obligation." + }, + "license": { + "type": "string", + "description": "The license associated with the obligation." + }, + "revisions": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "A dictionary where the key is the parent locator and the value is an array of locators in which the obligation was found." + } + }, + "example": { + "summary": "An example of a license obligation", + "value": { + "license": "BSD-4-Clause", + "description": "Describes whether the original copyright must be retained.", + "revisions": { + "sbom+1/my-sbom-project": [ + "npm+svelte$1.1.1" + ], + "custom+1/my-cli-project": [ + "npm+svelte$1.1.1" + ] + } + } + } + } + }, + "examples": { + "GetBowerConfig": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "hasUrl": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "hasUrl": true + } + ], + "useArtifactory": false + } + }, + "PutBowerConfig": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": { + "__type": "s", + "value": "www.existingPrivateBowerSite.com" + } + } + ], + "useArtifactory": true + } + }, + "GetGemConfig": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": "www.privategems.com/gems", + "username": "ruby_user", + "hasPassword": true + } + ] + } + }, + "PutGemConfig": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "url": "www.privategems.com/gems", + "username": "ruby_user", + "password": { + "__type": "s", + "value": "gemSecretPassword" + } + } + ] + } + }, + "GetMavenConfig": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "id": "Maven Private Server", + "url": "www.privatemaven.com/mvn" + } + ], + "servers": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "id": "Maven Private Server", + "username": "mvn_user", + "hasPassword": true + } + ] + } + }, + "PutMavenConfig": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000000", + "id": "Maven Private Server", + "url": "www.privatemaven.com/mvn" + } + ], + "servers": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "id": "Maven Private Server", + "username": "mvn_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + }, + "GetNugetConfig": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "username": "nuget_user", + "url": "www.nugetrepo.com/repo", + "hasPassword": true + } + ] + } + }, + "PutNugetConfig": { + "value": { + "sources": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.nugetrepo.com/repo", + "username": "nuget_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + }, + "GetPipConfig": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "username": "pip_user", + "url": "www.piprepo.com/repo", + "hasPassword": true + } + ] + } + }, + "PutPipConfig": { + "value": { + "repositories": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.piprepo.com/repo", + "username": "pip_user", + "password": { + "__type": "s", + "value": "secretPassword" + } + } + ] + } + }, + "GetGitConfig": { + "value": { + "authOptions": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "token", + "type": "oauth_key", + "hasToken": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "user/pass", + "type": "basic", + "username": "git_user", + "hasPassword": true + } + ] + } + }, + "PutGitConfig": { + "value": { + "authOptions": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "token", + "type": "oauth_key", + "value": { + "__type": "s", + "value": "123456789" + } + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "displayName": "user/pass", + "type": "basic", + "username": "git_user", + "password": { + "__type": "s", + "value": "password" + } + } + ] + } + }, + "GetNPMConfig": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth1", + "auth": { + "email": "foo@bar.com", + "username": "npm_user", + "hasPassword": true, + "hasToken": false, + "alwaysAuth": true + }, + "hasCa": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth2", + "auth": { + "hasToken": true, + "hasPassword": false + }, + "hasCa": true + } + ] + } + }, + "PutNPMConfig": { + "value": { + "registries": [ + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth1", + "auth": { + "email": "foo@bar.com", + "username": "npm_user", + "password": { + "__type": "s", + "value": "password" + } + }, + "hasCa": true + }, + { + "_id": "00000000-0000-0000-0000-000000000001", + "url": "www.npmauth.com/auth2", + "auth": { + "token": { + "__type": "s", + "value": "2324234234" + } + }, + "hasCa": true + } + ] + } + }, + "FossaUnauthorizedError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2010, + "message": "API token is invalid", + "name": "UnauthorizedError", + "httpStatusCode": 401 + } + }, + "FossaServerError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": -1, + "message": "Sorry, we've encountered an unexpected error. We've recorded it. If you continue to see this, contact support at support@fossa.com and include the unique reference code: 00000000-0000-0000-0000-000000000000", + "httpStatusCode": 500 + } + }, + "FossaForbiddenError": { + "value": { + "message": "Forbidden" + } + }, + "OrganizationNotFoundError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Organization not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "InvalidOrganizationSettingsPayload": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Couldn't update organization settings", + "name": "InvalidPayloadError", + "httpStatusCode": 422 + } + }, + "JiraNotFoundError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Jira with ID 123 not found in org with ID 12345.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "JiraUpdateBadRequest": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2003, + "message": "Parse error: expected undefined | null | string at root.base_url but found [4,5,6]", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "SingleJiraResponse": { + "value": { + "credentials": { + "basic": { + "username": "jira_user", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/00000000000/${issue.key}", + "id": 16, + "organizationId": 123, + "name": "Team 1 Jira site", + "base_url": "www.jira-site1.com", + "enabled": true, + "resolved_statuses": [ + "Done", + "Resolved", + "Closed" + ], + "resolvedStatusesEnabled": false, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "licensing-issue" + ], + "jiraProjectIds": [ + "PROD", + "STAG" + ], + "defaultLicensingProject": null, + "defaultSecurityProject": null, + "defaultQualityProject": null, + "createdAt": "2024-01-08T19:11:01.415Z" + } + }, + "MultipleJirasResponse": { + "value": [ + { + "credentials": { + "basic": { + "username": "jira_user", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/00000000000/${issue.key}", + "id": 16, + "organizationId": 123, + "name": "Team 1 Jira site", + "base_url": "www.jira-site1.com", + "enabled": true, + "resolved_statuses": [ + "Done", + "Resolved", + "Closed" + ], + "resolvedStatusesEnabled": false, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "licensing-issue" + ], + "jiraProjectIds": [ + "PROD", + "STAG" + ], + "defaultLicensingProject": null, + "defaultSecurityProject": null, + "defaultQualityProject": null, + "createdAt": "2024-01-08T19:11:01.415Z" + }, + { + "credentials": { + "basic": { + "username": "jira_user2", + "password": "········" + } + }, + "headers": {}, + "webhookURL": "https://app.fossa.com/hooks/jira/0000000000000/${issue.key}", + "id": 24, + "organizationId": 123, + "name": "Team 2 Jira site", + "base_url": "www.jira-site2.com", + "enabled": false, + "resolved_statuses": [ + "CustomDone" + ], + "resolvedStatusesEnabled": true, + "customFields": null, + "issueTypes": [], + "labels": [ + "exported-from-fossa", + "security-issue" + ], + "jiraProjectIds": [ + "PROD", + "TEST", + "DEV" + ], + "defaultLicensingProject": "PROD", + "defaultSecurityProject": "TEST", + "defaultQualityProject": "DEV", + "createdAt": "2024-01-08T19:11:01.415Z" + } + ] + }, + "JiraNewSite": { + "value": { + "name": "New Jira Site", + "enabled": true, + "base_url": "https://my-jira-site.com" + } + }, + "JiraUpdateBaseUrl": { + "value": { + "base_url": "https://my-jira-site.com" + } + }, + "JiraUpdateEnabled": { + "value": { + "enabled": true + } + }, + "JiraUpdateCredentialsAndLabels": { + "value": { + "credentials": { + "basic": { + "username": "jira_user", + "password": "password123" + } + }, + "labels": [ + "exported-from-fossa", + "licensing-issue" + ] + } + }, + "JiraUpdateHeadersAndCustomFields": { + "value": { + "headers": { + "x-token-test": "12345" + }, + "customFields": { + "12345": { + "fieldId": "12345", + "displayName": "Favorite soda", + "isRequired": false, + "defaultValue": "Sprite" + } + } + } + }, + "JiraUpdateComponents": { + "value": { + "components": [ + { + "id": "10001", + "displayName": "Component 1" + }, + { + "id": "10002", + "displayName": "Component 2" + } + ] + } + }, + "DeletedJiraFail": { + "value": { + "deleted": false, + "id": 1 + } + }, + "DeletedJiraSucceed": { + "value": { + "deleted": true, + "id": 1 + } + }, + "OrganizationPreferences": { + "value": { + "organizationId": 123, + "usesSAML": true, + "supportsCliLicenseScanning": true, + "supportsAnalyzedRevisionsQuery": true, + "supportsDependenciesCachePolling": true, + "supportsIssueDiffs": true, + "defaultVendoredDependencyScanType": "CLILicenseScan", + "supportsNativeContainerScans": true, + "requireFullFileUploads": true, + "supportsPathDependency": true, + "supportsFirstPartyScans": true, + "defaultToFirstPartyScans": false, + "customLicenseScanConfigs": [ + { + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + } + ] + } + }, + "GeneralOrganizationSettings": { + "value": { + "labels": [ + { + "label": "critical", + "id": 1, + "projectCount": 10 + } + ], + "title": "title", + "email": "test@fossa.com", + "defaultRoleId": 1, + "dependencySignatures": "1,2,3", + "disableNonCustomTeamUserRoles": false + } + }, + "EditingGeneralOrganizationSettings": { + "value": { + "labels": [ + "critical", + "low" + ], + "title": "title", + "email": "test@fossa.com", + "defaultRoleId": 1, + "dependencySignatures": "1,2,3", + "disableNonCustomTeamUserRoles": false + } + }, + "SecurityIssueSettings": { + "value": { + "defaultSecurityPolicyId": 1, + "projectDefaultSecurityIssueScanningEnabled": true, + "projectDefaultSecurityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterVulnerability": 4, + "projectDefaultSnippetSecurityIssueScanningEnabled": false + } + }, + "QualityIssueSettings": { + "value": { + "defaultQualityPolicyId": 1, + "projectDefaultQualityIssueScanningEnabled": true, + "projectDefaultQualityStatusCheckEnabled": true, + "projectDefaultStatusCheckFilterQuality": 1 + } + }, + "ContainerIssueSettings": { + "value": { + "projectDefaultExcludeBaseLayerIssuesLicensing": true, + "projectDefaultExcludeBaseLayerIssuesSecurity": true, + "projectDefaultExcludeBaseLayerIssuesQuality": true + } + }, + "NotificationsSettings": { + "value": { + "notificationDefaultEnabled": true, + "notificationDefaultSlackScan": true, + "notificationDefaultEmailScanUsers": [ + 1, + 2 + ], + "notificationDefaultEmailScanUserType": "all" + } + }, + "ProjectUpdateHooksSettings": { + "value": { + "updateHookDefaultScheduledEnabled": true, + "updateHookDefaultScheduledInterval": "week", + "updateHookDefaultScheduledIntervalLength": 77, + "updateHookDefaultScheduledIntervalTime": "2023-09-22T10:30:00Z" + } + }, + "AuthenticationSettings": { + "value": { + "subdomain": "example-test", + "loginSubdomain": "http://example-test..io:9578", + "disableInvite": true, + "saml": { + "callbackUrl": "http://example-test..io:9578/account/saml/1/callback", + "loginUrl": "http://example-test..io:9578/account/saml/1", + "audienceUrl": "http://example-test..io:9578/account/saml/1/ae1a20f1-0d1f-4356-a0d3-67c335763906", + "id": 39, + "organizationId": 1, + "entryPoint": "12", + "cert": "12", + "audience": "ae1a20f1-0d1f-4356-a0d3-67c335763906", + "createdAt": "2024-01-25T00:21:19.744Z", + "updatedAt": "2024-01-25T00:21:19.744Z" + }, + "ldap": { + "passwordIsSet": true, + "id": 3, + "organizationId": 1, + "enabled": false, + "server": "ldap.example.com", + "port": 636, + "ssl": true, + "username": "ldap_user", + "searchBase": "ou=users,dc=example,dc=com", + "searchFilter": "(objectClass=person)", + "useGroups": false, + "groupBase": "groupBase", + "groupFilter": "groupFilter2", + "groupNameAttr": "groupNameAttr", + "groupDNAttr": "groupDNAttr", + "userEmailAttr": "email", + "userNameAttr": "cn", + "uidAttr": "uid", + "allowEmptyEmail": false, + "createdAt": "2024-01-10T18:36:41.911Z", + "updatedAt": "2024-01-12T00:25:33.867Z" + }, + "sso": { + "google": true, + "saml": true, + "ldap": true + } + } + }, + "EditingAuthenticationSettings": { + "value": { + "disableInvite": false, + "subdomain": "test" + } + }, + "CustomLicenseScanSettings": { + "value": [ + { + "id": 1, + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + } + ] + }, + "PutCustomLicenseScanSettings": { + "value": [ + { + "id": 1, + "name": "Proprietary License", + "matchCriteria": "[Pp]roprietary [Ll]icense" + }, + { + "id": null, + "name": "Custom License", + "matchCriteria": "[Cc]ustom [Ll]icense" + } + ] + }, + "SlackSettings": { + "value": [ + { + "channel": "#fossa-licensing-notifications", + "webhook_url": "https://hooks.slack.com/services/ABCD/EFG/HIJK/LMNOP" + }, + { + "channel": "#fossa-security-notifications", + "webhook_url": "https://hooks.slack.com/services/QRST/UBWX/YZ12/3456" + } + ] + }, + "ProjectRevisionNotFoundError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This project revision does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "InvalidSBOMProjectError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "The revision is not associated with an SBOM", + "name": "BadRequestError", + "httpStatusCode": 400 + } + }, + "ReleaseNotFoundError": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "This release does not exist", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "ReleaseGroupNotFound": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release group (id: 1) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "ReleaseGroupReleaseNotFound": { + "value": { + "uuid": "00000000-0000-0000-0000-000000000000", + "code": 2004, + "message": "Release (id: 123) not found.", + "name": "NotFoundError", + "httpStatusCode": 404 + } + }, + "SourcedLicense": { + "value": { + "depth": 1, + "licenseId": "MIT", + "name": "MIT License", + "matches": [ + "npm+svelte$1.0.0", + "git+github.com/org/someproject$abcd1234", + "pip+pandas$9.8.7" + ], + "sources": [ + "git+github.com/myorg/myrepo$rev001", + "sbom+123/my-sbom-project$1.2.3", + "custom+123/some-cli-project$12345" + ] + } + }, + "Obligation": { + "summary": "An example of a license obligation", + "value": { + "license": "BSD-4-Clause", + "description": "Describes whether the original copyright must be retained.", + "revisions": { + "sbom+1/my-sbom-project": [ + "npm+svelte$1.1.1" + ], + "custom+1/my-cli-project": [ + "npm+svelte$1.1.1" + ] + } + } + } + } + } +} diff --git a/plugins/fossa/team_users_payload_test.go b/plugins/fossa/team_users_payload_test.go new file mode 100644 index 0000000..49b91e4 --- /dev/null +++ b/plugins/fossa/team_users_payload_test.go @@ -0,0 +1,112 @@ +package fossa + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" +) + +func TestResolveTeamAdminRoleID(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/roles" { + http.NotFound(w, r) + return + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[ + {"id":1,"scope":"organization","name":"Admin"}, + {"id":4,"scope":"team","name":"Team Admin"}, + {"id":5,"scope":"team","name":"Team Editor"} + ]`)) + })) + defer server.Close() + + client := &Client{ + APIKey: "test-token", + APIBase: server.URL, + } + + roleID, err := client.ResolveTeamAdminRoleID() + if err != nil { + t.Fatalf("ResolveTeamAdminRoleID returned error: %v", err) + } + if roleID != 4 { + t.Fatalf("roleID = %d, want %d", roleID, 4) + } +} + +func TestAddUserToTeamByEmailWithResponse_UsesCompatibilityPayloadShape(t *testing.T) { + var gotMethod string + var gotPath string + var gotAuth string + var gotBody map[string]any + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/users": + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`[{"id":94780,"email":"member@example.com"}]`)) + case "/teams/102209/users": + gotMethod = r.Method + gotPath = r.URL.Path + gotAuth = r.Header.Get("Authorization") + + defer r.Body.Close() + if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil { + t.Fatalf("decode request body: %v", err) + } + + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"id":102209,"users":[{"userId":94780,"roleId":3}]}`)) + default: + http.NotFound(w, r) + } + })) + defer server.Close() + + client := &Client{ + APIKey: "test-token", + APIBase: server.URL, + } + + resp, err := client.AddUserToTeamByEmailWithResponse(102209, "member@example.com", 3) + if err != nil { + t.Fatalf("AddUserToTeamByEmailWithResponse returned error: %v", err) + } + if resp == nil { + t.Fatal("AddUserToTeamByEmailWithResponse returned nil response") + } + + if gotMethod != http.MethodPut { + t.Fatalf("method = %q, want %q", gotMethod, http.MethodPut) + } + if gotPath != "/teams/102209/users" { + t.Fatalf("path = %q, want %q", gotPath, "/teams/102209/users") + } + if gotAuth != "Bearer test-token" { + t.Fatalf("authorization = %q, want %q", gotAuth, "Bearer test-token") + } + if gotBody["action"] != "add" { + t.Fatalf("action = %#v, want %q", gotBody["action"], "add") + } + + users, ok := gotBody["users"].([]any) + if !ok || len(users) != 1 { + t.Fatalf("users = %#v, want single-element array", gotBody["users"]) + } + + user, ok := users[0].(map[string]any) + if !ok { + t.Fatalf("users[0] = %#v, want object", users[0]) + } + if user["id"] != float64(94780) { + t.Fatalf("users[0].id = %#v, want %v", user["id"], 94780) + } + if user["userId"] != float64(94780) { + t.Fatalf("users[0].userId = %#v, want %v", user["userId"], 94780) + } + if user["roleId"] != float64(3) { + t.Fatalf("users[0].roleId = %#v, want %v", user["roleId"], 3) + } +} diff --git a/scripts/check-pii.sh b/scripts/check-pii.sh new file mode 100755 index 0000000..1512eda --- /dev/null +++ b/scripts/check-pii.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +ALLOWLIST_FILE="${ROOT_DIR}/scripts/pii-allowlist.regex" + +usage() { + echo "usage: $0 --staged | --ref-range " >&2 + exit 2 +} + +if [[ ! -f "${ALLOWLIST_FILE}" ]]; then + echo "missing allowlist file: ${ALLOWLIST_FILE}" >&2 + exit 2 +fi + +mode="${1:---staged}" +case "${mode}" in + --staged) + changed_files=$(git diff --cached --name-only --diff-filter=ACMR || true) + ;; + --ref-range) + if [[ $# -ne 3 ]]; then + usage + fi + from_ref="$2" + to_ref="$3" + changed_files=$(git diff --name-only --diff-filter=ACMR "${from_ref}" "${to_ref}" || true) + ;; + *) + usage + ;; +esac + +if [[ -z "${changed_files}" ]]; then + exit 0 +fi + +tmp_dir=$(mktemp -d) +trap 'rm -rf "${tmp_dir}"' EXIT + +is_allowed_match() { + local candidate="$1" + while IFS= read -r pattern; do + [[ -z "${pattern}" ]] && continue + [[ "${pattern}" =~ ^# ]] && continue + if [[ "${candidate}" =~ ${pattern} ]]; then + return 0 + fi + done <"${ALLOWLIST_FILE}" + return 1 +} + +render_file() { + local file="$1" + local target="$2" + if [[ "${mode}" == "--staged" ]]; then + git show ":${file}" >"${target}" + else + git show "${to_ref}:${file}" >"${target}" + fi +} + +fail=0 +for file in ${changed_files}; do + rendered_file="${tmp_dir}/$(basename "${file}")" + if ! render_file "${file}" "${rendered_file}" 2>/dev/null; then + continue + fi + if ! LC_ALL=C grep -Iq . "${rendered_file}"; then + continue + fi + + while IFS= read -r match; do + [[ -z "${match}" ]] && continue + line_no="${match%%:*}" + value="${match#*:}" + if ! is_allowed_match "${value}"; then + echo "ERROR: possible PII email in ${file}:${line_no}: ${value}" >&2 + fail=1 + fi + done < <(grep -nEo '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' "${rendered_file}" | sort -u || true) + + while IFS= read -r match; do + [[ -z "${match}" ]] && continue + line_no="${match%%:*}" + value="${match#*:}" + if ! is_allowed_match "${value}"; then + echo "ERROR: possible secret/token in ${file}:${line_no}: ${value}" >&2 + fail=1 + fi + done < <( + grep -nEo \ + 'ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|Bearer[[:space:]][A-Za-z0-9._=-]{16,}|sk-[A-Za-z0-9]{16,}|AKIA[0-9A-Z]{16}|-----BEGIN (RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----' \ + "${rendered_file}" | sort -u || true + ) +done + +if [[ "${fail}" -ne 0 ]]; then + echo "Commit blocked. Remove or sanitize PII/secrets, or extend the allowlist for approved fixtures." >&2 + exit 1 +fi diff --git a/scripts/check-sops-secrets.sh b/scripts/check-sops-secrets.sh new file mode 100755 index 0000000..1e9df86 --- /dev/null +++ b/scripts/check-sops-secrets.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail + +mode="${1:---staged}" + +case "${mode}" in + --staged) + changed_files=$(git diff --cached --name-only --diff-filter=ACMR | rg '^deploy/secrets/.*\.ya?ml$' || true) + ;; + --ref-range) + if [[ $# -ne 3 ]]; then + echo "usage: $0 --staged | --ref-range " >&2 + exit 2 + fi + from_ref="$2" + to_ref="$3" + changed_files=$(git diff --name-only --diff-filter=ACMR "${from_ref}" "${to_ref}" | rg '^deploy/secrets/.*\.ya?ml$' || true) + ;; + *) + echo "usage: $0 --staged | --ref-range " >&2 + exit 2 + ;; +esac + +if [[ -z "${changed_files}" ]]; then + exit 0 +fi + +tmp_dir=$(mktemp -d) +trap 'rm -rf "${tmp_dir}"' EXIT + +fail=0 +for file in ${changed_files}; do + rendered_file="${tmp_dir}/$(basename "${file}")" + if [[ "${mode}" == "--staged" ]]; then + git show ":${file}" >"${rendered_file}" + else + git show "${to_ref}:${file}" >"${rendered_file}" + fi + + if ! rg -q '^sops:' "${rendered_file}"; then + echo "ERROR: ${file} is missing sops metadata." >&2 + fail=1 + continue + fi + + while IFS= read -r line; do + [[ "${line}" =~ ^[[:space:]]*# ]] && continue + [[ "${line}" =~ ^[[:space:]]*$ ]] && continue + + if [[ "${line}" =~ ^[[:space:]]*([A-Za-z0-9_]*(TOKEN|SECRET|PASSWORD|KEY)[A-Za-z0-9_]*)[[:space:]]*:[[:space:]]*(.+)$ ]]; then + value="${BASH_REMATCH[3]}" + if [[ "${value}" != ENC[* ]]; then + echo "ERROR: ${file} contains unencrypted value for ${BASH_REMATCH[1]}." >&2 + fail=1 + fi + fi + done <"${rendered_file}" +done + +if [[ "${fail}" -ne 0 ]]; then + echo "Commit blocked. Encrypt secrets with SOPS before committing." >&2 + exit 1 +fi diff --git a/scripts/microcks-down.sh b/scripts/microcks-down.sh new file mode 100755 index 0000000..a5cf098 --- /dev/null +++ b/scripts/microcks-down.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +CONTAINER_TOOL=${CONTAINER_TOOL:-podman} +MICROCKS_CONTAINER_NAME=${MICROCKS_CONTAINER_NAME:-maintainerd-microcks} + +"${CONTAINER_TOOL}" rm -f "${MICROCKS_CONTAINER_NAME}" >/dev/null 2>&1 || true diff --git a/scripts/microcks-up.sh b/scripts/microcks-up.sh new file mode 100755 index 0000000..88cfb15 --- /dev/null +++ b/scripts/microcks-up.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +CONTAINER_TOOL=${CONTAINER_TOOL:-podman} +MICROCKS_CONTAINER_NAME=${MICROCKS_CONTAINER_NAME:-maintainerd-microcks} +MICROCKS_PORT=${MICROCKS_PORT:-8585} +MICROCKS_IMAGE=${MICROCKS_IMAGE:-quay.io/microcks/microcks-uber:latest-native} +MICROCKS_ARTIFACT=${MICROCKS_ARTIFACT:-$ROOT_DIR/microcks/fossa-api-mock.yaml} + +if [ ! -r "${MICROCKS_ARTIFACT}" ]; then + echo "Microcks artifact is not readable: ${MICROCKS_ARTIFACT}" >&2 + exit 1 +fi + +dump_logs() { + "${CONTAINER_TOOL}" logs "${MICROCKS_CONTAINER_NAME}" 2>&1 || true +} + +"${CONTAINER_TOOL}" rm -f "${MICROCKS_CONTAINER_NAME}" >/dev/null 2>&1 || true + +"${CONTAINER_TOOL}" run -d \ + --name "${MICROCKS_CONTAINER_NAME}" \ + -p "${MICROCKS_PORT}:8080" \ + "${MICROCKS_IMAGE}" >/dev/null + +ready="" +for _ in $(seq 1 90); do + if curl -sf "http://localhost:${MICROCKS_PORT}/" >/dev/null 2>&1; then + ready=1 + break + fi + sleep 1 +done + +if [ -z "${ready}" ]; then + echo "Microcks did not become ready on port ${MICROCKS_PORT}" >&2 + dump_logs >&2 + exit 1 +fi + +if ! curl -fsS \ + --retry 10 \ + --retry-delay 2 \ + --retry-connrefused \ + --retry-all-errors \ + "http://localhost:${MICROCKS_PORT}/api/artifact/upload?mainArtifact=true" \ + -F "file=@${MICROCKS_ARTIFACT}" >/dev/null; then + echo "Failed to upload Microcks artifact: ${MICROCKS_ARTIFACT}" >&2 + dump_logs >&2 + exit 1 +fi + +echo "MICROCKS_URL=http://localhost:${MICROCKS_PORT}" +echo "FOSSA_API_BASE=http://localhost:${MICROCKS_PORT}/rest/FOSSA%20API/4.32.3" diff --git a/scripts/pii-allowlist.regex b/scripts/pii-allowlist.regex new file mode 100644 index 0000000..f2d8a2c --- /dev/null +++ b/scripts/pii-allowlist.regex @@ -0,0 +1,17 @@ +# Reserved/example fixture domains. +^[A-Za-z0-9._%+-]+@(example\.com|example\.org|example\.net|example\.dev|example\.test|test\.dev|github\.example|github\.test|affiliated-company\.tld|users\.noreply\.github\.com|example\.invalid)$ + +# Approved vendor/support addresses that may appear in checked-in API docs. +^[A-Za-z0-9._%+-]+@fossa\.com$ + +# Placeholder addresses present in vendor API documentation. +^email@email\.com$ +^api-service@company\.com$ +^prod-api@company\.com$ +^automation@company\.com$ +^foo@bar\.com$ + +# Common documentation placeholders. +^Bearer[[:space:]]+REDACTED$ +^Bearer[[:space:]]+TOKEN$ +^Bearer[[:space:]]+\.\.\.$ diff --git a/web/cucumber.js b/web/cucumber.js index a5fb3a4..9d0c6b4 100644 --- a/web/cucumber.js +++ b/web/cucumber.js @@ -9,7 +9,9 @@ const junitReportPath = module.exports = { default: { - paths: ["../features/web/**/*.feature"], + paths: process.env.WEB_BDD_FEATURE + ? [process.env.WEB_BDD_FEATURE] + : ["../features/web/**/*.feature"], require: ["tests/steps/**/*.js"], tags: "not @wip", format: [ diff --git a/web/src/app/maintainers/[id]/page.tsx b/web/src/app/maintainers/[id]/page.tsx index 042d5c3..6130cc3 100644 --- a/web/src/app/maintainers/[id]/page.tsx +++ b/web/src/app/maintainers/[id]/page.tsx @@ -8,6 +8,9 @@ import MaintainerEditCard, { CompanyOption, MaintainerEditDraft, } from "@/components/MaintainerEditCard"; +import MaintainerServicesPanel, { + MaintainerServiceView, +} from "@/components/MaintainerServicesPanel"; import CompanyCreateModal from "@/components/CompanyCreateModal"; import styles from "./page.module.css"; @@ -21,6 +24,7 @@ type MaintainerDetail = { companyId?: number | null; company?: string; projects: { id: number; name: string }[]; + services?: MaintainerServiceView[]; createdAt: string; updatedAt: string; updatedBy?: string; @@ -43,6 +47,7 @@ const maintainerDataHasChanged = ( current.status !== next.status || current.company !== next.company || current.companyId !== next.companyId || + JSON.stringify(current.services ?? []) !== JSON.stringify(next.services ?? []) || current.createdAt !== next.createdAt || current.updatedAt !== next.updatedAt || current.updatedBy !== next.updatedBy || @@ -440,6 +445,20 @@ export default function MaintainerPage() { updatedNotice={saveNotice} /> )} + {role === "staff" && maintainer?.services?.length ? ( + { + const data = next as MaintainerDetail; + setMaintainer((prev) => + prev ? (maintainerDataHasChanged(prev, data) ? data : prev) : data + ); + }} + services={maintainer.services} + /> + ) : null} diff --git a/web/src/components/MaintainerServicesPanel.module.css b/web/src/components/MaintainerServicesPanel.module.css new file mode 100644 index 0000000..55c1c0f --- /dev/null +++ b/web/src/components/MaintainerServicesPanel.module.css @@ -0,0 +1,301 @@ +.panel { + display: grid; + gap: 16px; +} + +.card { + padding: 24px; + border-radius: 18px; + background: var(--md-card-bg, #ffffff); + box-shadow: var(--md-shadow, 0 12px 24px rgba(0, 0, 0, 0.08)); + color: var(--md-card-text, #0f172a); +} + +.cardContent { + padding: 24px; +} + +.header { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 16px; + margin-bottom: 20px; +} + +.title { + margin: 0; + font-size: 22px; + color: var(--md-card-text-strong, #0b1220); +} + +.subtitle { + margin: 6px 0 0; + color: var(--md-card-muted, rgba(15, 23, 42, 0.68)); + font-size: 14px; + line-height: 1.4; +} + +.summary { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: flex-end; +} + +.summaryItem { + padding: 6px 10px; + border-radius: 999px; + background: rgba(15, 23, 42, 0.08); + font-size: 12px; + font-weight: 600; +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 16px; +} + +.actionButton { + border: 0; + border-radius: 999px; + padding: 10px 14px; + background: #0f766e; + color: #f8fafc; + font-size: 13px; + font-weight: 700; + cursor: pointer; +} + +.actionButton:disabled { + opacity: 0.6; + cursor: default; +} + +.notice { + margin-bottom: 16px; + color: #0f5132; + font-size: 14px; + font-weight: 600; +} + +.section { + border-top: 1px solid var(--md-border, rgba(15, 23, 42, 0.08)); + padding-top: 16px; + margin-top: 16px; +} + +.sectionTitle { + margin: 0 0 12px; + font-size: 14px; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--md-card-muted, rgba(15, 23, 42, 0.6)); +} + +.accountGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 10px 18px; +} + +.stateRow { + grid-column: 1 / -1; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; + padding: 2px 0 10px; +} + +.detailRow { + display: flex; + justify-content: space-between; + gap: 14px; + padding: 6px 0; +} + +.detailLabel { + font-weight: 600; + color: var(--md-card-text-strong, #0b1220); +} + +.detailValue { + text-align: right; +} + +.remoteLink { + color: #d62293; + font-weight: 600; + text-decoration: none; +} + +.remoteLink:hover { + text-decoration: underline; +} + +.stateText { + display: inline-flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + color: var(--md-card-text, #0f172a); + font-size: 14px; +} + +.stateEmail { + font-weight: 600; +} + +.stateSource { + display: inline-flex; + align-items: center; + gap: 6px; + color: var(--md-card-muted, rgba(15, 23, 42, 0.7)); + font-size: 13px; +} + +.inlineIcon { + width: 14px; + height: 14px; + display: block; +} + +.inlineActionButton { + border: 0; + border-radius: 999px; + padding: 8px 12px; + background: #d62293; + color: #ffffff; + font-size: 12px; + font-weight: 700; + cursor: pointer; +} + +.inlineActionButton:disabled { + opacity: 0.6; + cursor: default; +} + +.badge { + display: inline-flex; + align-items: center; + padding: 5px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.2px; +} + +.badge_default { + background: rgba(15, 23, 42, 0.12); + color: #0b1220; +} + +.badge_registered { + background: #14532d; + color: #dcfce7; + box-shadow: inset 0 0 0 1px rgba(187, 247, 208, 0.22); +} + +.badge_member { + background: rgba(16, 185, 129, 0.18); + color: #0f5132; +} + +.badge_invited { + background: #78350f; + color: #fef3c7; + box-shadow: inset 0 0 0 1px rgba(253, 230, 138, 0.2); +} + +.badge_pending { + background: rgba(245, 158, 11, 0.18); + color: #8a4b00; +} + +.badge_not_registered { + background: #334155; + color: #e2e8f0; + box-shadow: inset 0 0 0 1px rgba(226, 232, 240, 0.14); +} + +.badge_missing { + background: rgba(239, 68, 68, 0.14); + color: #991b1b; +} + +.badge_error { + background: #7f1d1d; + color: #fee2e2; + box-shadow: inset 0 0 0 1px rgba(254, 202, 202, 0.2); +} + +.tableWrap { + overflow-x: auto; + border: 1px solid var(--md-border, rgba(15, 23, 42, 0.08)); + border-radius: 12px; + background: var(--md-card-bg, #ffffff); +} + +.table { + width: 100%; + border-collapse: collapse; + font-size: 13px; + color: var(--md-card-text, #0f172a); +} + +.table th, +.table td { + text-align: left; + padding: 10px 12px; + border-bottom: 1px solid rgba(15, 23, 42, 0.08); + vertical-align: top; +} + +.table th { + font-size: 12px; + font-weight: 600; + letter-spacing: 0.6px; + text-transform: uppercase; + color: var(--md-card-text-strong, #0b1220); +} + +.targetName { + display: block; + font-weight: 600; +} + +.empty { + color: var(--md-card-muted, rgba(15, 23, 42, 0.6)); + font-size: 14px; +} + +.errorText { + color: #991b1b; +} + +@media (max-width: 720px) { + .cardContent { + padding: 16px; + } + + .header { + flex-direction: column; + } + + .summary { + justify-content: flex-start; + } + + .detailRow { + flex-direction: column; + gap: 4px; + } + + .detailValue { + text-align: left; + } +} diff --git a/web/src/components/MaintainerServicesPanel.tsx b/web/src/components/MaintainerServicesPanel.tsx new file mode 100644 index 0000000..7895516 --- /dev/null +++ b/web/src/components/MaintainerServicesPanel.tsx @@ -0,0 +1,434 @@ +"use client"; + +import { useEffect, useState } from "react"; +import Link from "next/link"; +import { Card } from "clo-ui/components/Card"; +import styles from "./MaintainerServicesPanel.module.css"; + +export type MaintainerServiceAccount = { + state: string; + matchedBy: string; + remoteUserId?: number; + remoteRef?: string; + emailUsed?: string; + lastCheckedAt?: string; + pendingInvitations?: number; + acceptedInvitations?: number; + error?: string; +}; + +export type MaintainerServiceTarget = { + projectId: number; + projectName: string; + targetKind: string; + targetId?: number; + targetName: string; + required: boolean; + state: string; + pendingInvite?: boolean; + lastCheckedAt?: string; + error?: string; +}; + +export type MaintainerServiceView = { + kind: string; + label: string; + account: MaintainerServiceAccount; + targets: MaintainerServiceTarget[]; +}; + +type MaintainerServicesPanelProps = { + apiBaseUrl: string; + maintainerId: number; + disabled?: boolean; + onMaintainerUpdated: (next: unknown) => void; + services: MaintainerServiceView[]; +}; + +const accountStateLabel: Record = { + registered: "Registered", + invited: "Invited", + not_registered: "Not Registered", + unknown: "Unknown", + error: "Error", +}; + +const targetStateLabel: Record = { + member: "Member", + missing: "Missing", + pending: "Pending", + error: "Error", + not_applicable: "Not Applicable", +}; + +const targetKindLabel: Record = { + team: "Team", + organization: "Organization", + project: "Project", + mailing_list: "Mailing List", +}; + +function buildFossaTeamHref(targetId?: number) { + if (typeof targetId !== "number") { + return null; + } + return `https://app.fossa.com/account/settings/organization/teams/${targetId}`; +} + +function buildFossaUserHref(remoteUserId?: number) { + if (typeof remoteUserId !== "number") { + return null; + } + return `https://app.fossa.com/account/settings/organization/users/${remoteUserId}`; +} + +function formatDateTime(value?: string | null) { + if (!value) { + return "—"; + } + const parsed = new Date(value); + if (Number.isNaN(parsed.getTime())) { + return "—"; + } + return parsed.toLocaleString("en-US", { + dateStyle: "medium", + timeStyle: "short", + }); +} + +function AccountStateBadge({ state }: { state: string }) { + const label = accountStateLabel[state] || state; + return ( + + {label} + + ); +} + +function WorkEmailIcon() { + return ( + + ); +} + +function GitHubIcon() { + return ( + + ); +} + +function TargetStateBadge({ state }: { state: string }) { + const label = targetStateLabel[state] || state; + return ( + + {label} + + ); +} + +function ServiceAccountStatus({ + account, + canInvite, + disabled = false, + isInviting = false, + onInvite, + serviceKind, +}: { + account: MaintainerServiceAccount; + canInvite: boolean; + disabled?: boolean; + isInviting?: boolean; + onInvite: () => void; + serviceKind: string; +}) { + const remoteUserHref = + serviceKind === "fossa" ? buildFossaUserHref(account.remoteUserId) : null; + const showPendingInvites = (account.pendingInvitations ?? 0) > 0; + const showAcceptedInvites = (account.acceptedInvitations ?? 0) > 0; + const statusSourceLabel = + account.matchedBy === "github_email" ? "GitHub" : account.matchedBy === "maintainer_email" ? "Work" : null; + + return ( +
+
+ + {account.state === "registered" || account.state === "invited" ? ( + <> + {account.emailUsed ? ( + + using {account.emailUsed} + {statusSourceLabel ? ( + + {account.matchedBy === "github_email" ? : } + {statusSourceLabel} + + ) : null} + + ) : null} + + ) : null} + {account.state === "not_registered" && canInvite ? ( + + ) : null} + {account.state === "error" && account.error ? ( + {account.error} + ) : null} + {remoteUserHref ? ( + + FOSSA User Account + + ) : null} +
+ {showPendingInvites ? ( +
+ Pending Invites + {account.pendingInvitations} +
+ ) : null} + {showAcceptedInvites ? ( +
+ Accepted Invites + {account.acceptedInvitations} +
+ ) : null} +
+ ); +} + +function ServiceTargetMembershipTable({ + serviceKind, + targets, +}: { + serviceKind: string; + targets: MaintainerServiceTarget[]; +}) { + if (targets.length === 0) { + return
No service targets are required for this maintainer.
; + } + + return ( +
+ + + + + + + + + + + + + + {targets.map((target) => ( + + + + + + + + + + ))} + +
ProjectTarget TypeRemote TargetRequiredStateLast CheckedError
+ {target.projectName} + {targetKindLabel[target.targetKind] || target.targetKind} + {serviceKind === "fossa" && buildFossaTeamHref(target.targetId) ? ( + + {target.targetName} + + ) : ( + {target.targetName} + )} + {target.required ? "Yes" : "No"} + + {formatDateTime(target.lastCheckedAt)}{target.error || "—"}
+
+ ); +} + +function actionLabel(action: "refresh" | "invite" | "reconcile") { + switch (action) { + case "refresh": + return "Refresh"; + case "invite": + return "Send Invite"; + case "reconcile": + return "Reconcile Missing"; + default: + return action; + } +} + +function MaintainerServiceCard({ + apiBaseUrl, + disabled = false, + maintainerId, + onMaintainerUpdated, + service, +}: { + apiBaseUrl: string; + disabled?: boolean; + maintainerId: number; + onMaintainerUpdated: (next: unknown) => void; + service: MaintainerServiceView; +}) { + const missingCount = service.targets.filter((target) => target.state === "missing").length; + const pendingCount = service.targets.filter((target) => target.state === "pending").length; + const [activeAction, setActiveAction] = useState<"refresh" | "invite" | "reconcile" | null>(null); + const [actionError, setActionError] = useState(null); + const [actionNotice, setActionNotice] = useState(null); + + const canInvite = service.kind === "fossa" && service.account.state === "not_registered"; + const canReconcile = + service.kind === "fossa" && + service.account.state === "registered" && + missingCount > 0; + + useEffect(() => { + if (!actionNotice) { + return; + } + const timer = window.setTimeout(() => setActionNotice(null), 5000); + return () => window.clearTimeout(timer); + }, [actionNotice]); + + const handleAction = async (action: "refresh" | "invite" | "reconcile") => { + setActiveAction(action); + setActionError(null); + try { + const response = await fetch( + `${apiBaseUrl}/maintainers/${maintainerId}/services/${service.kind}/${action}`, + { + method: "POST", + credentials: "include", + } + ); + if (!response.ok) { + const message = await response.text(); + throw new Error(message || `unexpected status ${response.status}`); + } + const data = await response.json(); + onMaintainerUpdated(data); + setActionNotice(`${actionLabel(action)} completed`); + } catch (error) { + setActionError(error instanceof Error ? error.message : "Action failed"); + } finally { + setActiveAction(null); + } + }; + + return ( + +
+
+
+

{service.label}

+
+
+ {service.targets.length} targets + {missingCount} missing + {pendingCount} pending +
+
+ +
+ + {canReconcile ? ( + + ) : null} +
+ {actionNotice ?
{actionNotice}
: null} + {actionError ?
{actionError}
: null} + +
+

Remote Service User Account

+ void handleAction("invite")} + serviceKind={service.kind} + /> +
+ +
+

Project Target Memberships

+ +
+
+
+ ); +} + +export default function MaintainerServicesPanel({ + apiBaseUrl, + maintainerId, + disabled = false, + onMaintainerUpdated, + services, +}: MaintainerServicesPanelProps) { + if (services.length === 0) { + return null; + } + + return ( +
+ {services.map((service) => ( + + ))} +
+ ); +} diff --git a/web/tests/MICROCKS.MD b/web/tests/MICROCKS.MD new file mode 100644 index 0000000..187ec8a --- /dev/null +++ b/web/tests/MICROCKS.MD @@ -0,0 +1,98 @@ +# Web BDD With Microcks + +This document describes how to run the web BDD suite against a mocked FOSSA API +using Microcks. + +## Why Microcks + +The web BDD suite exercises FOSSA-backed flows such as: + +- choosing FOSSA for a project +- listing FOSSA team state on the License Checker page +- refreshing maintainer service state +- sending FOSSA invites +- reconciling missing FOSSA team memberships + +Those flows are more reliable under test when the FOSSA API is mocked. + +## Mock Artifact + +The mock contract lives at: + +- [`microcks/fossa-api-mock.yaml`](/home/rk/cncf/gh/maintainer-d/microcks/fossa-api-mock.yaml) + +The supporting scripts are: + +- [`scripts/microcks-up.sh`](/home/rk/cncf/gh/maintainer-d/scripts/microcks-up.sh) +- [`scripts/microcks-down.sh`](/home/rk/cncf/gh/maintainer-d/scripts/microcks-down.sh) + +## Run The Web BDD Suite + +The simplest path is: + +```bash +WEB_BDD_USE_MICROCKS=true make test-web +``` + +This flow will: + +- reset and seed the local test database +- start Microcks automatically +- import the FOSSA mock artifact +- point `web-bff` at the Microcks mock base URL +- build and start the web app +- run the Playwright/Cucumber BDD suite +- stop Microcks during cleanup + +## Run A Single Feature + +To run only one feature file: + +```bash +WEB_BDD_USE_MICROCKS=true \ +BDD_FEATURE=../features/web/maintainer_profile.feature \ +make test-web +``` + +Example for the project License Checker feature: + +```bash +WEB_BDD_USE_MICROCKS=true \ +BDD_FEATURE=../features/web/license_checker.feature \ +make test-web +``` + +## Manual Local Use + +If you want Microcks available outside the Make target: + +```bash +scripts/microcks-up.sh +``` + +Microcks UI: + +```text +http://localhost:8585 +``` + +The mock base URL used by `web-bff` is: + +```text +http://localhost:8585/rest/FOSSA%20API/4.32.3 +``` + +When finished: + +```bash +scripts/microcks-down.sh +``` + +## Notes + +- The mock reflects observed live FOSSA behavior for `PUT /teams/{id}/users`, + including the currently required `users[].id` request field. +- The web BDD seed data is created by + [`cmd/web-bff-seed/main.go`](/home/rk/cncf/gh/maintainer-d/cmd/web-bff-seed/main.go). +- The Cucumber step definitions live under + [`web/tests/steps`](/home/rk/cncf/gh/maintainer-d/web/tests/steps). diff --git a/web/tests/steps/license_checker.steps.js b/web/tests/steps/license_checker.steps.js index e4b271f..f8d7e36 100644 --- a/web/tests/steps/license_checker.steps.js +++ b/web/tests/steps/license_checker.steps.js @@ -49,6 +49,14 @@ const openLicenseCheckerSection = async (world) => { }); }; +const activeInvitationSection = (world) => + world.page + .getByRole("heading", { name: "ACTIVE MAINTAINERS ELIGABLE FOR INVITATION" }) + .locator("..") + .locator(".."); + +const activeInvitationRows = (world) => activeInvitationSection(world).locator("tbody tr"); + Given("the project has selected FOSSA", function () { if (!this.projectName) { this.projectName = projectNames.fossaPartial; @@ -121,12 +129,20 @@ Then("the ACTIVE MAINTAINERS ELIGABLE FOR INVITATION table is visible", async fu }); When("I select maintainers in the table", async function () { - const checkbox = this.page.getByRole("checkbox").first(); + const checkboxes = activeInvitationRows(this).getByRole("checkbox"); + const count = await checkboxes.count(); + for (let index = 0; index < count; index += 1) { + const checkbox = checkboxes.nth(index); + if (await checkbox.isChecked()) { + await checkbox.uncheck(); + } + } + const checkbox = checkboxes.first(); await checkbox.check(); }); When("I clear the maintainer selection", async function () { - const checkboxes = this.page.getByRole("checkbox"); + const checkboxes = activeInvitationRows(this).getByRole("checkbox"); const count = await checkboxes.count(); for (let index = 0; index < count; index += 1) { const checkbox = checkboxes.nth(index); @@ -287,14 +303,21 @@ Then("I see a note that the project may have an organization on Snyk", async fun Then( "the invite action shows Send CNCF FOSSA Invites to {int} Selected Maintainers", async function (count) { - const label = `Send CNCF FOSSA Invites to ${count} Selected Maintainers`; - await expect(this.page.getByRole("button", { name: label })).toBeVisible({ timeout: 15000 }); + const button = this.page.getByRole("button", { name: /Send CNCF FOSSA Invites to/i }); + await expect(button).toBeVisible({ timeout: 15000 }); + await expect(button).toHaveText( + new RegExp(`Send CNCF FOSSA Invites to ${count} Selected Maintainers`, "i"), + { timeout: 15000 } + ); } ); Then("the invite action is disabled when {int} is {int}", async function (_count, selected) { - const label = new RegExp(`Send CNCF FOSSA Invites to ${selected} Selected Maintainers`, "i"); - const button = this.page.getByRole("button", { name: label }); + const button = this.page.getByRole("button", { name: /Send CNCF FOSSA Invites to/i }); + await expect(button).toHaveText( + new RegExp(`Send CNCF FOSSA Invites to ${selected} Selected Maintainers`, "i"), + { timeout: 15000 } + ); await expect(button).toBeDisabled({ timeout: 15000 }); }); diff --git a/web/tests/steps/maintainer_service.steps.js b/web/tests/steps/maintainer_service.steps.js new file mode 100644 index 0000000..1dc836b --- /dev/null +++ b/web/tests/steps/maintainer_service.steps.js @@ -0,0 +1,343 @@ +const { Given, When, Then } = require("@cucumber/cucumber"); +const { expect } = require("@playwright/test"); + +const seededMaintainers = { + antonio: { + name: "Antonio Example", + email: "antonio.example@test.dev", + github: "antonio-example", + }, + renee: { + name: "Renee Sample", + email: "renee.sample@example.dev", + github: "renee-sample", + }, + alex: { + name: "Alex Example", + email: "alex@example.dev", + github: "alex-example", + }, + diego: { + name: "Diego Placeholder", + email: "diego.placeholder@test.dev", + github: "diego-placeholder", + }, + jun: { + name: "Jun Example", + email: "jun.example@test.dev", + github: "jun-example", + }, + sam: { + name: "Sam NoEmail", + email: "EMAIL_MISSING", + github: "sam-noemail", + }, +}; + +const resolveMaintainerIdByQuery = async (world, query) => { + const response = await world.page.request.get( + `${world.bffBaseUrl}/api/search?query=${encodeURIComponent(query)}` + ); + if (!response.ok()) { + throw new Error(`Failed to search maintainers: ${response.status()}`); + } + const payload = await response.json(); + const maintainers = Array.isArray(payload.maintainers) ? payload.maintainers : []; + const exact = maintainers.find( + (maintainer) => + maintainer.name === query || + maintainer.email === query || + maintainer.github === query || + maintainer.githubAccount === query + ); + const match = exact || maintainers[0]; + if (!match?.id) { + throw new Error(`No maintainer found for query "${query}"`); + } + return String(match.id); +}; + +const selectSeededMaintainer = async (world, key) => { + const maintainer = seededMaintainers[key]; + if (!maintainer) { + throw new Error(`Unknown seeded maintainer persona "${key}"`); + } + world.selectedMaintainer = maintainer; + world.maintainerId = await resolveMaintainerIdByQuery( + world, + maintainer.github || maintainer.name + ); + return world.maintainerId; +}; + +const resolveMaintainerId = async (world) => { + if (world.maintainerId) { + return world.maintainerId; + } + if (process.env.TEST_MAINTAINER_ID) { + world.maintainerId = process.env.TEST_MAINTAINER_ID; + return world.maintainerId; + } + const meResponse = await world.page.request.get(`${world.bffBaseUrl}/api/me`); + if (!meResponse.ok()) { + throw new Error(`Failed to load /api/me: ${meResponse.status()}`); + } + const meData = await meResponse.json(); + if (meData.maintainerId) { + world.maintainerId = meData.maintainerId; + return world.maintainerId; + } + throw new Error("No TEST_MAINTAINER_ID configured and /api/me did not return a maintainerId"); +}; + +const openMaintainerPage = async (world) => { + const maintainerId = await resolveMaintainerId(world); + await world.page.goto(`${world.baseUrl}/maintainers/${maintainerId}`, { + waitUntil: "domcontentloaded", + }); + await expect(world.page.getByRole("heading", { name: /.+/ }).first()).toBeVisible({ + timeout: 15000, + }); +}; + +const serviceCard = (world, label = "CNCF FOSSA") => + world.page.getByRole("heading", { name: label }); + +Given("a maintainer exists in maintainer-d", async function () { + const response = await this.page.request.get(`${this.bffBaseUrl}/healthz`); + if (!response.ok()) { + throw new Error(`BFF health check failed: ${response.status()}`); + } +}); + +Given("the maintainer belongs to one or more projects", async function () { + await selectSeededMaintainer(this, "antonio"); +}); +Given("the maintainer is associated with a project that uses FOSSA", async function () { + this.serviceKind = "fossa"; + await selectSeededMaintainer(this, "sam"); +}); +Given("the maintainer belongs to a project that uses FOSSA", async function () { + this.serviceKind = "fossa"; + await selectSeededMaintainer(this, "alex"); +}); +Given("the maintainer belongs to multiple active projects that use FOSSA", async function () { + this.serviceKind = "fossa"; + await selectSeededMaintainer(this, "renee"); +}); +Given("the maintainer belongs to one or more projects that use FOSSA", async function () { + this.serviceKind = "fossa"; + await selectSeededMaintainer(this, "jun"); +}); +Given("the maintainer exists in CNCF FOSSA", async function () { + if (!this.maintainerId) { + await selectSeededMaintainer(this, "renee"); + } +}); +Given("the maintainer does not exist in CNCF FOSSA", async function () { + await selectSeededMaintainer(this, "diego"); +}); +Given("the maintainer is not a member of that project's FOSSA team", async function () { + await selectSeededMaintainer(this, "alex"); +}); +Given("the maintainer is missing from one or more required FOSSA teams", async function () { + await selectSeededMaintainer(this, "renee"); +}); +Given("a CNCF FOSSA invitation is pending for the maintainer", async function () { + await selectSeededMaintainer(this, "jun"); +}); + +When("I open the maintainer page", async function () { + await openMaintainerPage(this); +}); + +When("I update the maintainer email address", async function () { + await openMaintainerPage(this); + const nextEmail = + process.env.TEST_UPDATED_MAINTAINER_EMAIL || "bob@affiliated-company.tld"; + const editCard = this.page + .getByRole("heading", { name: "Update maintainer" }) + .first() + .locator(".."); + await expect(editCard).toBeVisible({ timeout: 15000 }); + const editButton = editCard.getByRole("button", { name: "Edit" }); + await expect(editButton).toBeVisible({ timeout: 15000 }); + await editButton.click(); + const emailInput = this.page.getByRole("textbox", { name: "Email" }); + await expect(emailInput).toBeEnabled({ timeout: 15000 }); + await emailInput.fill(nextEmail); + this.updatedMaintainerEmail = nextEmail; +}); + +When("I save the maintainer record", async function () { + const saveButton = this.page.getByRole("button", { name: "Save changes" }); + await expect(saveButton).toBeEnabled({ timeout: 15000 }); + const responsePromise = this.page.waitForResponse( + (response) => + response.request().method() === "PATCH" && + /\/api\/maintainers\/\d+$/.test(response.url()), + { timeout: 20000 } + ); + await saveButton.click(); + const response = await responsePromise; + if (!response.ok()) { + throw new Error(`Save maintainer failed: ${response.status()} ${await response.text()}`); + } + await expect( + this.page.getByRole("heading", { name: "Update maintainer" }) + ).toBeVisible({ timeout: 15000 }); +}); + +When("I refresh the maintainer's remote service associations", async function () { + await openMaintainerPage(this); + const button = this.page.getByRole("button", { name: "Refresh" }); + await expect(button).toBeVisible({ timeout: 15000 }); + const responsePromise = this.page.waitForResponse( + (response) => + response.request().method() === "POST" && + /\/api\/maintainers\/\d+\/services\/fossa\/refresh$/.test(response.url()), + { timeout: 20000 } + ); + await button.click(); + const response = await responsePromise; + if (!response.ok()) { + throw new Error(`Refresh remote service associations failed: ${response.status()} ${await response.text()}`); + } +}); + +When("I reconcile the maintainer's FOSSA access from the maintainer page", async function () { + await openMaintainerPage(this); + const button = this.page.getByRole("button", { name: "Reconcile Missing" }); + await expect(button).toBeVisible({ timeout: 15000 }); + const responsePromise = this.page.waitForResponse( + (response) => + response.request().method() === "POST" && + /\/api\/maintainers\/\d+\/services\/fossa\/reconcile$/.test(response.url()), + { timeout: 20000 } + ); + await button.click(); + const response = await responsePromise; + if (!response.ok()) { + throw new Error(`Reconcile FOSSA access failed: ${response.status()} ${await response.text()}`); + } +}); + +When("I send a CNCF FOSSA invite from the maintainer page", async function () { + await openMaintainerPage(this); + const button = this.page.getByRole("button", { name: "Send Invite" }); + await expect(button).toBeVisible({ timeout: 15000 }); + const responsePromise = this.page.waitForResponse( + (response) => + response.request().method() === "POST" && + /\/api\/maintainers\/\d+\/services\/fossa\/invite$/.test(response.url()), + { timeout: 20000 } + ); + await button.click(); + const response = await responsePromise; + if (!response.ok()) { + throw new Error(`Send FOSSA invite failed: ${response.status()} ${await response.text()}`); + } +}); + +When("the FOSSA invitation is accepted", function () { + // External side-effect. The following refresh step re-reads remote state. +}); + +Then("I see a service associations section", async function () { + await expect(serviceCard(this)).toBeVisible({ timeout: 15000 }); + await expect( + this.page.getByRole("heading", { name: "Remote Service User Account" }) + ).toBeVisible({ timeout: 15000 }); +}); + +Then("I see which remote services the maintainer is associated with", async function () { + await expect(this.page.getByRole("heading", { name: "CNCF FOSSA" })).toBeVisible({ + timeout: 15000, + }); +}); + +Then("I see which project service assignments imply that the maintainer should be associated with those services", async function () { + await expect(this.page.getByRole("heading", { name: "Project Target Memberships" })).toBeVisible({ + timeout: 15000, + }); + await expect(this.page.getByRole("columnheader", { name: "Project" })).toBeVisible({ + timeout: 15000, + }); + await expect(this.page.getByRole("columnheader", { name: "Remote Target" })).toBeVisible({ + timeout: 15000, + }); +}); + +Then("maintainer-d checks whether the maintainer exists on the remote service using the updated maintainer email address", async function () { + const email = this.updatedMaintainerEmail || process.env.TEST_UPDATED_MAINTAINER_EMAIL; + if (!email) { + return; + } + await expect(this.page.locator('[class*="stateEmail"]').getByText(email)).toBeVisible({ + timeout: 15000, + }); +}); + +Then("maintainer-d may also check using the maintainer GitHub email address", function () { + // Lookup strategy is internal. UI exposes the matched source when known. +}); + +Then("the maintainer page shows the updated remote service association status", async function () { + await expect(this.page.locator('[class*="badge_"]').first()).toBeVisible({ + timeout: 15000, + }); +}); + +Then("I see that the maintainer is associated with CNCF FOSSA", async function () { + await expect(this.page.getByText("Registered").first()).toBeVisible({ timeout: 15000 }); +}); + +Then("I see that the maintainer is missing from the FOSSA team required by the project", async function () { + await expect(this.page.getByText("Missing").first()).toBeVisible({ + timeout: 15000, + }); +}); + +Then("maintainer-d adds the maintainer to every missing required FOSSA team using the FOSSA REST API", function () { + // Covered by the POST reconcile request completing successfully. +}); + +Then("the maintainer page shows the full set of required FOSSA teams for the maintainer", async function () { + const rows = this.page.locator("tbody tr"); + await expect.poll(async () => rows.count(), { timeout: 15000 }).toBeGreaterThan(0); +}); + +Then("the maintainer page shows that the maintainer is now associated with those FOSSA teams", async function () { + const memberBadges = this.page.getByText("Member"); + await expect(memberBadges.first()).toBeVisible({ timeout: 15000 }); +}); + +Then("maintainer-d sends a CNCF FOSSA invitation to the maintainer", function () { + // Covered by the POST invite request completing successfully. +}); + +Then("the maintainer page shows that FOSSA onboarding is pending", async function () { + await expect(this.page.getByText("Invited").first()).toBeVisible({ timeout: 15000 }); +}); + +Then("maintainer-d reconciles the maintainer to each required FOSSA team", function () { + // Covered by refresh completing after invite acceptance. +}); + +Then("the maintainer page shows that the maintainer is associated with those FOSSA teams", async function () { + const memberBadges = this.page.getByText("Member"); + await expect(memberBadges.first()).toBeVisible({ timeout: 15000 }); +}); + +Then("I see whether the maintainer was matched by maintainer email address or GitHub email address", async function () { + const workSource = this.page.locator('[class*="stateSource"]').getByText("Work", { + exact: true, + }); + const githubSource = this.page.locator('[class*="stateSource"]').getByText("GitHub", { + exact: true, + }); + await Promise.race([ + expect(workSource).toBeVisible({ timeout: 15000 }), + expect(githubSource).toBeVisible({ timeout: 15000 }), + ]); +});