REST API

Package intelligence API

One GET endpoint that merges npm registry metadata, semver-aware “safe” version picks, and OSV signals—optionally enriched with GitHub release notes.

Overview

Call GET /api/npm/{package} at https://safeversion.com to get a single JSON document: npm package metadata, suggested “safe” versions under a minimum publish-age rule (see policy.minAgeDays in the response), OSV-backed security context, useful links, and—if you ask for it—release-note snippets. The playground on this site issues requests to the same origin you are viewing.

To wire SafeVersion into your own project and agents, follow Onboarding below (script, policy rule, and optional extras).

Installs and upgrades should go through this API instead of guessing from npm latest alone.

Responses are application/json with Cache-Control: no-store. Response time depends on the package, OSV checks, and whether you enable release notes.

Onboarding

In your app repository, install the wrapper script and a policy rule so agents use SafeVersion before any pnpm add or npm install that pulls new versions. The steps below are ordered; optional steps cover other tools and hand-edited package.json flows.

Step 1 — Add the wrapper script

  1. Copy scripts/safeversion-add.mjs from the SafeVersion project into your repo (same filename under scripts/).
  2. In package.json, add "safeversion:add": "node scripts/safeversion-add.mjs".
  3. Add packages with pnpm safeversion:add -- <package>. Put pnpm flags before package names (for example pnpm safeversion:add -- -D @types/node). The script asks https://safeversion.com for a safe version, then runs pnpm add with it.

Step 2 — Add the policy rule

Agents working only in the terminal often skip file-scoped rules. Install a project rule that always applies so every session is told to use pnpm safeversion:add instead of raw installs.

  1. Download safeversion-dependencies.mdc.
  2. Save it as .cursor/rules/safeversion-dependencies.mdc in your repo.
  3. Keep alwaysApply: true in the file frontmatter so the rule is always active.

Current rule file (reference)

---
description: Use pnpm safeversion:add only; never raw package installs until SafeVersion picks a safe version
alwaysApply: true
---

# SafeVersion before dependency changes

**Local / agent installs (vibecode path).** This project does not rely on CI for dependency policy—**your machine runs install scripts as soon as you install**, so consult SafeVersion **before** any add/install.

## MUST use this command to add packages

Use **only**:

```bash
pnpm safeversion:add -- <package> [more packages...]
```

Optional `pnpm` flags **before** package names (e.g. `-D`, `--save-dev`):

```bash
pnpm safeversion:add -- -D @types/node
```

- The wrapper calls `https://safeversion.com` (same `/api/npm/…` paths).
- If SafeVersion is unreachable, **do not** fall back to arbitrary installs—report the error and fix connectivity (network, firewall, or DNS to `https://safeversion.com`).

## MUST NOT (until SafeVersion has chosen the version)

Do **not** run **`npm install`**, **`npm i`**, **`pnpm add`**, **`pnpm install`** (to add deps), **`yarn add`**, **`bun add`**, or equivalent for **new** or **upgraded** dependencies. The **`pnpm safeversion:add`** script calls SafeVersion then runs `pnpm add` with the safe version.

Removing packages or editing `package.json` by hand is still governed below when you need version advice.

## Manual API path (e.g. editing package.json without running add)

If you cannot use the script, follow **`.cursor/skills/safeversion-package-intelligence/SKILL.md`** and:

1. `encodeURIComponent` scoped names (`@scope/pkg` → one path segment).
2. `GET` `https://safeversion.com/api/npm/{package}` with `Accept: application/json`.
3. With an installed version, pass `?current=` (**exact** semver when possible). Prefer **`smallestSafeUpgrade`** when stepping from `current`, else **`latestSafe`**. If `latestSafe` is null with stable-only policy, retry with **`prerelease=1`** per the skill.
4. Read **`warnings`** and **`security`** before finalizing.
5. On API errors or timeouts, do **not** invent a “safe” version.

**Scope:** Governs **adding**, **removing**, and **bumping** npm dependencies in `package.json` and lockfiles when you touch them.

Step 3 — Optional: AGENTS.md

If your workflow uses tools that read AGENTS.md instead of Cursor rules, add equivalent instructions at the repo root (or merge into an existing file).

# SafeVersion

Use **only** `pnpm safeversion:add -- <package>` to add npm dependencies. Optional flags before package names are passed through to `pnpm add` (e.g. `pnpm safeversion:add -- -D @types/node`).

Do **not** run `pnpm add`, `npm install`, `npm i`, `yarn add`, or `bun add` for new packages until SafeVersion has suggested a version—those commands run install scripts immediately.

The wrapper calls `https://safeversion.com`.

Step 4 — Optional: agent skill

When someone edits package.json by hand or calls the HTTP API directly, an agent skill helps with path encoding, query parameters, and retries. It does not replace the script and rule above.

  1. Download SKILL.md
  2. Save as .cursor/skills/safeversion-package-intelligence/SKILL.md in the project, or install it as a user skill from your editor's agent-skills settings.

API reference on this page: Endpoint, Query parameters, and Errors. Quick usage: new packages → latestSafe and warnings; upgrades → ?current= with exact semver for smallestSafeUpgrade; releaseNotes=1 is slower (see errors for timeouts).

Endpoint

GET /api/npm/{package}

Path

GET /api/npm/{package}

{package} is a single URL segment. Use percent-encoding for scoped names, e.g. @types/node%40types%2Fnode. The playground builds this for you.

Alternate name query

You may pass ?name= to override the path segment (decoded the same way). If both are empty after trim, the API returns 400.

Query parameters

NameTypeRequiredDescription
namestringNoOptional override for the package name (instead of the path segment only).
currentstringNoInstalled version as exact semver. When valid, the response includes smallestSafeUpgrade: the lowest safe version strictly greater than current. Invalid semver → 400.
releaseNotesflagNoWhen 1, true, or yes (case-insensitive), the response may include a releaseNotes object with summaries fetched from GitHub for tags matching latestSafe / smallestSafeUpgrade. Expect slower responses; entries may be missing if the repo has no matching release.

Response body

On success you get a JSON object with the fields below. Omitted keys mean “not applicable” (for example smallestSafeUpgrade appears only when you passed current).

FieldMeaning
packageDisplay name from the packument (fallback: requested name).
requestedCurrentEcho of normalized current when supplied.
latestSafeNewest version that satisfies the age window and (when OSV succeeds) has no known vulnerabilities in the checked set—or null if none.
smallestSafeUpgradeWith current: lowest safe version > current, or null if none. Omitted entirely without current.
policyminAgeDays tells you how many days after publish a version must be before it can qualify as “safe” for this API. prerelease is currently always "excluded" (pre-release versions are not candidates).
securityprovider: "osv", assessedAt ISO timestamp, status ok or unknown if OSV failed.
linksnpm URL, optional repository, and when GitHub is known + current is set: compareToLatestSafe / compareToSmallestSafeUpgrade compare URLs.
releaseNotesPresent when requested: optional entries for latestSafe / smallestSafeUpgrade with tag, summary, and URL.
warningsHuman-readable issues: empty age window, OSV failure, no clean versions, etc.

Each safe version includes version, publishedAt (ISO), and satisfies: an array such as ["ageWindow"] and optionally "osvClean".

Errors

StatusBodyWhen
400{ "error": "Missing package name" }No usable name from path or query.
400{ "error": "Invalid semver for query parameter current" }Malformed current.
404{ "error": "Package not found" }Registry returned 404.
502{ "error": "Could not read package metadata" }Oversized or invalid packument JSON.
502{ "error": "Registry request failed" }Non-OK response from npm registry.
504{ "error": "Upstream request timed out" }The request did not finish in time (upstream work exceeded the timeout).
500{ "error": "Internal server error" }Unexpected failure.

Interactive examples

Each playground runs a real fetch to the same host you opened the docs on. Use the sidebar under Interactive examples to jump between recipes.

Baseline: latest safe

When to use: You only need the newest “safe” version and general policy / security context—omit current so smallestSafeUpgrade is not computed.

RequestGET

Must be a valid semver string when set.

/api/npm/react

Response
Run a request to see status, timing, and JSON here.

With current version

When to use: You know what is installed and want the next safe bump (e.g. for PR bots or dashboards). Pass a valid semver as current to populate smallestSafeUpgrade and compare links when a GitHub repo exists on the packument.

RequestGET

Must be a valid semver string when set.

/api/npm/react?current=18.0.0

Response
Run a request to see status, timing, and JSON here.

Scoped package

When to use: Scoped packages must occupy a single path segment; the playground encodes @scope/name automatically for the request URL.

RequestGET

Must be a valid semver string when set.

/api/npm/%40types%2Fnode?current=20.0.0

Response
Run a request to see status, timing, and JSON here.

Release notes

When to use: You want human-readable release text alongside version picks. Responses are slower and release bodies may be absent depending on the package's GitHub tags and rate limits.

RequestGET

Must be a valid semver string when set.

/api/npm/semver?current=7.5.0&releaseNotes=1

Response
Run a request to see status, timing, and JSON here.