API and MCP

Portfolios

Named sets of subjects scored together: their scores, the ranked fixes that would move them, the subjects themselves, criticality ratings and accepted risks

List portfolios

GET /api/v1/project/{projectId}/v1/portfolio

Credentials: API token or dashboard sign-in.

Every portfolio in this project. A portfolio is a named set of subjects scored together; each entry carries its portfolio_id, name, members (each with member_type and value) and whether it is the built-in portfolio that holds every subject (is_implicit). Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.

Responses

Status Description Body
200 The project's portfolios, under portfolios. PortfolioList
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 Portfolios are not set up for this project yet. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Create a portfolio

POST /api/v1/project/{projectId}/v1/portfolio

Credentials: API token or dashboard sign-in.

Creates a portfolio with a name and, optionally, its first members. Scoring begins immediately; until it finishes, the portfolio's state and rank answer 503. Requires project:portfolio:view and project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.

Request body

application/json (required)

CreatePortfolioRequest

Responses

Status Description Body
201 The new portfolio. PortfolioResponse
400 name is missing or blank, or a member is invalid. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 Portfolios are not set up for this project yet. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X POST "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio" \
  -H "Authorization: Bearer $SPICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '<JSON body>'

Get a portfolio

GET /api/v1/project/{projectId}/v1/portfolio/{portfolioId}

Credentials: API token or dashboard sign-in.

One portfolio by id: its name, members and settings. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID

Responses

Status Description Body
200 The portfolio. PortfolioResponse
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Update a portfolio

PUT /api/v1/project/{projectId}/v1/portfolio/{portfolioId}

Credentials: API token or dashboard sign-in.

Renames a portfolio and/or replaces its members. name sets the name; members replaces the whole member list, each {"type": "subject" | "package", "value": ...}. A changed membership rescores the portfolio. The built-in portfolio (is_implicit) cannot be edited. Requires project:portfolio:view and project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID

Request body

application/json (required)

UpdatePortfolioRequest

Responses

Status Description Body
200 The updated portfolio. PortfolioResponse
400 A member is invalid, or this is the built-in portfolio, which cannot be edited. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X PUT "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>" \
  -H "Authorization: Bearer $SPICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '<JSON body>'

Delete a portfolio

DELETE /api/v1/project/{projectId}/v1/portfolio/{portfolioId}

What it changes: Its scores and history stop being served. The subjects themselves are untouched.

Credentials: API token or dashboard sign-in.

Deletes a portfolio. It leaves the list and its reads answer 404; its subjects and their criticality ratings are untouched. The built-in portfolio (is_implicit) cannot be deleted. Requires project:portfolio:view and project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID

Responses

Status Description Body
204 The portfolio is deleted.
400 This is the built-in portfolio, which cannot be deleted. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it was already deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X DELETE "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Get portfolio history

GET /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/history

Credentials: API token or dashboard sign-in.

The portfolio's scores over time: one row per score movement, each with its axis, score, band, what caused the change and when. The axis query parameter limits the rows to one of pqc, vuln or agility. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID
axis query string Only this score axis: pqc, vuln or agility (default: every axis)

Responses

Status Description Body
200 The score history, under rows. ScoreHistory
400 axis is not pqc, vuln or agility. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/history" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

List portfolio members

GET /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/member

Credentials: API token or dashboard sign-in.

The members of a portfolio, each a subject or a package. The built-in portfolio lists every subject in the project. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID

Responses

Status Description Body
200 The members under members, each with member_type (subject or package) and value. ModuleMemberList
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/member" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Add a member to a portfolio

POST /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/member

Credentials: API token or dashboard sign-in.

Adds one member, {"type": "subject" | "package", "value": ...}; a plain string is a subject. Adding a member that is already present changes nothing. The portfolio is rescored. The built-in portfolio (is_implicit) cannot be changed. Requires project:portfolio:view and project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID

Request body

application/json (required)

MemberSpec

Responses

Status Description Body
200 The members after the addition, under members. ModuleMemberList
400 The member is invalid, or this is the built-in portfolio, which cannot be changed. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X POST "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/member" \
  -H "Authorization: Bearer $SPICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '<JSON body>'

Remove a member from a portfolio

DELETE /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/member/{value}

What it changes: The portfolio's scores are worked out again without this member.

Credentials: API token or dashboard sign-in.

Removes one member, named by its value in the path, with its kind in the type query parameter: subject (the default) or package. The portfolio is rescored. The built-in portfolio (is_implicit) cannot be changed. Requires project:portfolio:view and project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID
value required path string The member value, URL-encoded: a subject name, or a package URL without a version
type query string subject (default) or package

Responses

Status Description Body
200 The members after the removal, under members. ModuleMemberList
400 type is neither subject nor package, or this is the built-in portfolio, which cannot be changed. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has no such member. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X DELETE "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/member/<value>" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Get portfolio rank

GET /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/rank

Credentials: API token or dashboard sign-in.

The ranked list of fixes for a portfolio, best first, one page at a time. offset (default 0) and limit (default 50) query parameters choose the page; rows keep their overall rank number. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID
offset query integer Index in the whole list of the first fix to return (default 0)
limit query integer Page size, 1 to 10000 (default 1000)
summary query boolean Smaller rows: no items, and at most the 10 most important findings and 10 most important occurrences per row; reach still counts every subject (default false)

Responses

Status Description Body
200 A page of ranked fixes under rows, with total, offset and limit. RankPage
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The portfolio has not been scored yet (code is unscored), is being rescored after a change (code is rescoring), or the project's data is temporarily unreachable; try again shortly. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/rank" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Simulate portfolio fixes

POST /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/simulate

Credentials: API token or dashboard sign-in.

What the portfolio's score would be if the named fixes were applied. The body is one fix, a list of fixes, or {"fixes": [...]}. A fix names a row of the ranked list in item_key; on its own that means fixing everything on the row. Add finding_key to fix one finding of the row, or dependency (a library the row bundles) to upgrade that library, never both; upgrade_to sets the version to upgrade to, and defaults to the known fixed version. The answer holds the current and projected scores, marked as projected; add the rank=true query parameter to get the re-ranked fix list as well. Nothing is changed. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID
rank query boolean Also return the fix list as it would stand after the fixes (default false)

Request body

The fixes to simulate

application/json (required)

SimulateFixes

Responses

Status Description Body
200 The projected scores, marked as projected. Simulation
400 No fix was given, a fix gives both finding_key and dependency, or a fix names a row that is not in the ranked list, a finding or library the row does not carry, or an upgrade that cannot apply to it. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X POST "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/simulate" \
  -H "Authorization: Bearer $SPICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '<JSON body>'

Get portfolio state

GET /api/v1/project/{projectId}/v1/portfolio/{portfolioId}/state

Credentials: API token or dashboard sign-in.

The portfolio's current score and its breakdown by axis and by subject, with the time it was computed. The ranked fix list is left out unless the rank=true query parameter asks for it; the rank endpoint serves it in pages. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
portfolioId required path string (uuid) The portfolio ID
rank query boolean Include the full ranked list of fixes (default false)

Responses

Status Description Body
200 The current state. PortfolioState
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No portfolio with this id exists in this project, or it has been deleted. Error
500 A fault on our side. Error
503 The portfolio has not been scored yet (code is unscored), is being rescored after a change (code is rescoring), or the project's data is temporarily unreachable; try again shortly. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/portfolio/<portfolioId>/state" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Regenerate a report

POST /api/v1/project/{projectId}/v1/report/{jobId}/regenerate

Credentials: API token or dashboard sign-in.

Asks for a new version of a report under the current report version. A posture report is rebuilt from the same data as of the same date. A survey's report is rebuilt by a new survey that reuses the analysis the survey already has, with no new upload. The old version stays readable. The answer's job_id is the job to follow: the new posture report, or for a survey's report the new survey; supersedes names the posture report or survey it replaces. A report is regenerated once: while its new version is being produced, and after it is ready, a further request answers 409. If the new version fails, or is still waiting to start after 30 minutes, you may ask again. Requires project:edit.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
jobId required path string (uuid) The report's job ID: a survey's report step, or a posture report
Idempotency-Key header string or null Optional; repeating a key returns the first answer for a survey's report

Responses

Status Description Body
202 Regeneration requested: job_id is the job to follow and supersedes names what it replaces. RegenerateReportResponse
400 The report belongs to a survey that has no upload to rebuild from. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No report with this job id exists in this project, or its portfolio has been deleted. Error
409 This report was already regenerated, or a new version is already being produced. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X POST "https://api.spicelabs.io/api/v1/project/<projectId>/v1/report/<jobId>/regenerate" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

List subjects

GET /api/v1/project/{projectId}/v1/subject

Credentials: API token or dashboard sign-in.

Every subject in this project. A subject is a thing being scored, such as an application or a component; each carries its current criticality and when it was first and last seen. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.

Responses

Status Description Body
200 The subjects, under subjects. SubjectList
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 Portfolios are not set up for this project yet. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/subject" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

List a subject's contents

GET /api/v1/project/{projectId}/v1/subject/{subject}/content

Credentials: API token or dashboard sign-in.

The items currently inside a subject, one page at a time. offset (default 0) and limit query parameters choose the page. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
subject required path string The subject's name
offset query integer Index of the first item to return (default 0)
limit query integer Page size, 1 to 10000 (default 1000)

Responses

Status Description Body
200 A page of the subject's current contents. SubjectContents
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No subject with this name exists in this project. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/subject/<subject>/content" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"

Rate a subject's criticality

PUT /api/v1/project/{projectId}/v1/subject/{subject}/criticality

Credentials: Dashboard sign-in only. API tokens are refused.

Records how important a subject is. The body carries value, one of high, medium, low or unclassified, and an optional rationale. The caller is recorded as the rater. Ratings are kept as a history and never overwritten, and every portfolio holding the subject is rescored. Only a dashboard session may call this, never an API token. Requires project:portfolio:rate.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
subject required path string The subject's name

Request body

application/json (required)

RateCriticality

Responses

Status Description Body
200 The recorded rating: its value, the prior_value, the rater and when. CriticalityRating
400 value is missing, or is not one of high, medium, low or unclassified. Error
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 No subject with this name exists in this project. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X PUT "https://api.spicelabs.io/api/v1/project/<projectId>/v1/subject/<subject>/criticality" \
  -H "Authorization: Bearer $SPICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '<JSON body>'

Get criticality history

GET /api/v1/project/{projectId}/v1/subject/{subject}/criticality/history

Credentials: API token or dashboard sign-in.

Every criticality rating a subject has received, each with its value, the prior_value it replaced, who rated it, the rationale and when. A subject that has never been rated gives an empty list. Requires project:portfolio:view.

Parameters

Name In Type Description
projectId required path string (uuid) The project's id.
subject required path string The subject's name

Responses

Status Description Body
200 The subject's ratings. array of CriticalityEventResponse
401 The token is missing, expired, revoked or of the wrong kind. Error
403 The token is valid but not allowed to do this. Error
404 Portfolios are not set up for this project yet. Error
500 A fault on our side. Error
503 The project's data is temporarily unreachable; code says why. Error

Example

curl -X GET "https://api.spicelabs.io/api/v1/project/<projectId>/v1/subject/<subject>/criticality/history" \
  -H "Authorization: Bearer $SPICE_API_TOKEN"