Plans: Every plan. Reading keeps working while the workspace is read-only or closed. Who: anyone with a read
token, or an agent connected over OAuth; owners and admins create read tokens.
Authentication
Every request needs a read token in theAuthorization header:
401 here, and a read token gets 401 on the upload and alert destination endpoints. See
create a token.
A read token stops working when the person who created it leaves the company or stops being an owner or admin. The audit
trail records it as revoked by Pharus, with the reason.
An agent connected over OAuth with the workspace:read scope reads the same endpoints with its own token (pho_...). See
the MCP server.
What the responses contain
- Field names are in English, and so are the audit trail’s titles. Dates are ISO 8601 in UTC.
- Every item has a
urlto the same thing in Pharus. - The responses never contain drafts of reports to the authorities, a reporter’s details, email addresses, member ids or token hashes. Owners show as names.
- Responses are sent with
Cache-Control: private, no-store.
Example: overdue fixes
Vulnerabilities
List vulnerabilities
GET /api/v1/vulnerabilities returns one row per vulnerability, component and product family, 50 per page, as on the
Vulnerabilities list. Matches of archived product families are
left out. The query parameters are the list’s filters; an invalid value is ignored.
The response is
{ vulnerabilities, total, page, pageCount, pageSize }. Each row has:
Get a vulnerability
GET /api/v1/vulnerabilities/{id} takes a CVE, GHSA or EUVD id, for example CVE-2026-1234. It returns the
vulnerability with every match in the workspace, as on its page in Pharus:
404 with not_found when no product in the workspace matches the vulnerability.
Incidents
List incidents
GET /api/v1/incidents returns the workspace’s incidents, without drills. status=open, the default, lists open
incidents with the nearest deadline first; status=closed lists closed ones, the most recently closed first.
The response is { incidents, counts, truncated }: at most 500 incidents, counts with the number open and closed,
and truncated when there are more than were returned. Each incident has:
Get an incident
GET /api/v1/incidents/{reference} takes the reference in any case, for example INC-0042. It returns what happened,
the decision, every regime’s clocks and what was filed. It never contains the drafts of the reports.
A clock’s
state is pending (not started yet), running, overdue, submitted, received or not_required. See
clocks.
404 with not_found when the workspace has no incident with that reference.
Audit trail
GET /api/v1/events returns the audit trail, newest first.
The response is
{ events, nextBefore }. nextBefore is null on the last page. Each event has the id, occurredAt,
the action key (for example report.submitted), the title and detail as the page shows them in English, the
actor and actorKind (user, system, api_token, partner for the Pharus team, or agent), onBehalfOf (the person
an agent acted for, otherwise null), and the incident reference when there is one. Email addresses are removed, and so are a reporter’s subject line, the recipients of invoices and
pages, and why someone is off call.
SBOMs
List SBOMs
GET /api/v1/sboms returns the SBOMs of the active product families, newest first, 50 per page. family (a product
family’s id) narrows it to one family, retired=1 includes SBOMs that a newer one replaced or a person retired, and
page picks the page.
The response is { sboms, total, page, pageCount, pageSize }. Each SBOM has its id, family, productVersion,
format and specVersion, the source (upload, github, azure_devops, dependency_track, sbomify or api), the
status (received, parsed, matched or failed, with the error), componentCount, receivedAt, retiredAt, the
quality check as the upload response gives it, and endOfLifeComponents: how many
components are on a release line past end of life upstream.
Get an SBOM
GET /api/v1/sboms/{id} returns one SBOM with its details (productName, serialNumber, the ci details sent with it,
sha256, sizeBytes, parsedAt, matchedAt and uploadedBy) and its components, those with the most exploited and
known vulnerabilities first. Each component has its name, group, version, purl and cpe, the number of
vulnerabilities and how many of them are exploited, and endOfLife (product, cycle, from) when its release
line is past end of life.
A retired SBOM’s components have no vulnerabilities: Pharus only checks the SBOMs in use.
Advisories
List advisories
GET /api/v1/advisories returns the workspace’s security advisories, the most recently
updated first. status (draft, in_review or published) narrows the list. The response is
{ advisories, truncated }: at most 500, with truncated when there are more. Each advisory has its trackingId,
title, status, tlp, vulnerabilities, families, currentVersion, updatedAt and the incident reference.
Get an advisory
GET /api/v1/advisories/{trackingId} takes the tracking ID in any case. Besides the fields of the list, it returns
the publicUrl, the releases (version, tlp, publishedAt, publishedBy, filename and publicUrl of each), the
CSAF document of the current release as csaf, and while a new version is a draft or in review, the CSAF document it would
publish as draftCsaf.
Deadlines
GET /api/v1/deadlines returns every deadline in the workspace, nearest first. Overdue ones are always in. The rest come
within within_days, from 1 to 90 days ahead. The default is 14. Drills and archived product families are left out.
The response is { deadlines, now, withinDays, fixesTruncated }. fixesTruncated is true when there were more than the
200 nearest fix deadlines. Each deadline has a kind, its deadline, overdue and a url, and:
Product families
GET /api/v1/families returns the active product families, by name, as { families }. Each has its id, name, description, currentVersion, memberStates, soldInEu, newestSbomOnly, componentCount, lastSbomAt and url. newestSbomOnly is true when only the newest SBOM is in use: each new SBOM retires every older one in the family, not just the one for its own version.
Errors
Errors have the same shape as everywhere in the API:{ "error": "...", "message": "..." }. See
responses.
Each read token can make 600 requests per hour, counted together across the read endpoints.