API Reference

Find Incidents by Affected Package

Search supply-chain incidents by an affected package name. Matches are case-insensitive and substring-based, so ethers matches ethers-jss. Results are returned newest first by the incident's published date.

GET
/v1/supply-chain/packages

Cost: 1 credit per successful call

Query parameters

namestringrequired

The package name (or fragment) to search for. 1 to 200 characters. Matched case-insensitively as a substring against affected package names.

ecosystemstringoptionaldefault: (all)

Restrict results to a single package ecosystem (e.g. npm, pypi, crates, docker, github-actions). A slug of up to 40 characters, lowercased server-side. Omit to search all ecosystems.

limitintegeroptionaldefault: 50

Maximum number of package matches to return. Accepted range: 1–200.

Request

curl "https://api.precursorintelligence.com/functions/v1/supply-chain/packages?name=time&ecosystem=crates&limit=50" \
  -H "Authorization: Bearer $PRECURSOR_API_KEY"

Response

200 OK
{
  "data": {
    "count": 3,
    "items": [
      {
        "incident_id": "crates-2026-02-28-time-utility-typosquats",
        "ecosystem": "crates",
        "package_name": "time_calibrator",
        "affected_versions": ["0.1.0"],
        "incident_title": "Rust crates.io time-utility typosquat cluster",
        "severity": "high",
        "published": "2026-02-28"
      },
      {
        "incident_id": "crates-2026-02-28-time-utility-typosquats",
        "ecosystem": "crates",
        "package_name": "time-sync",
        "affected_versions": ["0.1.0"],
        "incident_title": "Rust crates.io time-utility typosquat cluster",
        "severity": "high",
        "published": "2026-02-28"
      },
      {
        "incident_id": "crates-2026-02-28-time-utility-typosquats",
        "ecosystem": "crates",
        "package_name": "chrono_anchor",
        "affected_versions": ["0.1.0"],
        "incident_title": "Rust crates.io time-utility typosquat cluster",
        "severity": "high",
        "published": "2026-02-28"
      }
    ],
    "generated_at": "2026-05-18T10:24:31.118Z"
  },
  "meta": {
    "request_id": "8b16efb8-9a6c-4ace-b817-11cbee626d08",
    "generated_at": "2026-05-18T10:24:31.118Z",
    "credits": { "charged": 1, "remaining": 9998 }
  }
}

Response fields

data.countintegeroptional

Number of package matches returned (equals items.length).

data.itemsarrayoptional

The matching affected-package rows, ordered by incident published descending. Each object contains the fields below. A single incident may appear multiple times, once per matching package.

data.items[].incident_idstringoptional

Identifier of the incident this package belongs to. Pass to GET /v1/supply-chain/incidents/{id} for the full record.

data.items[].ecosystemstringoptional

Package ecosystem (e.g. npm, pypi, crates, docker, github-actions).

data.items[].package_namestringoptional

The affected package name.

data.items[].affected_versionsarrayoptional

Array of affected version strings. May be empty when specific versions were not enumerated.

data.items[].incident_titlestringoptional

Title of the incident this package belongs to.

data.items[].severitystringoptional

Severity of the incident: low, medium, high, or critical.

data.items[].publishedstringoptional

ISO 8601 date (YYYY-MM-DD) the incident was first published.

data.generated_atstringoptional

ISO 8601 UTC timestamp indicating when this response was produced.

Errors

StatuserrorWhen
400missing_nameThe required name query parameter was not supplied.
400invalid_namename is empty after trimming or exceeds 200 characters.
400invalid_ecosystemecosystem exceeds 40 characters or contains characters outside [A-Za-z0-9_-].
400invalid_limitlimit is not an integer, or is outside the 1–200 range.
401invalid_authorizationThe Authorization header is missing or malformed.
401unauthorizedThe key is invalid, revoked, or the request IP is not on the allowlist.
402insufficient_creditsThe organisation's credit balance is below 1.
404not_foundThe route or resource does not exist.
405method_not_allowedOnly GET and OPTIONS are accepted.
500internalAn unexpected server error occurred.

See Errors for the full error reference.