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
- Copy
scripts/safeversion-add.mjsfrom the SafeVersion project into your repo (same filename underscripts/). - In
package.json, add"safeversion:add": "node scripts/safeversion-add.mjs". - Add packages with
pnpm safeversion:add -- <package>. Put pnpm flags before package names (for examplepnpm safeversion:add -- -D @types/node). The script askshttps://safeversion.comfor a safe version, then runspnpm addwith 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.
- Download safeversion-dependencies.mdc.
- Save it as
.cursor/rules/safeversion-dependencies.mdcin your repo. - Keep
alwaysApply: truein 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.
- Download SKILL.md
- Save as
.cursor/skills/safeversion-package-intelligence/SKILL.mdin 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
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
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No | Optional override for the package name (instead of the path segment only). |
| current | string | No | Installed version as exact semver. When valid, the response includes smallestSafeUpgrade: the lowest safe version strictly greater than current. Invalid semver → 400. |
| releaseNotes | flag | No | When 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).
| Field | Meaning |
|---|---|
| package | Display name from the packument (fallback: requested name). |
| requestedCurrent | Echo of normalized current when supplied. |
| latestSafe | Newest version that satisfies the age window and (when OSV succeeds) has no known vulnerabilities in the checked set—or null if none. |
| smallestSafeUpgrade | With current: lowest safe version > current, or null if none. Omitted entirely without current. |
| policy | minAgeDays 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). |
| security | provider: "osv", assessedAt ISO timestamp, status ok or unknown if OSV failed. |
| links | npm URL, optional repository, and when GitHub is known + current is set: compareToLatestSafe / compareToSmallestSafeUpgrade compare URLs. |
| releaseNotes | Present when requested: optional entries for latestSafe / smallestSafeUpgrade with tag, summary, and URL. |
| warnings | Human-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
| Status | Body | When |
|---|---|---|
| 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.
Must be a valid semver string when set.
→ /api/npm/react
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.
Must be a valid semver string when set.
→ /api/npm/react?current=18.0.0
Scoped package
When to use: Scoped packages must occupy a single path segment; the playground encodes @scope/name automatically for the request URL.
Must be a valid semver string when set.
→ /api/npm/%40types%2Fnode?current=20.0.0
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.
Must be a valid semver string when set.
→ /api/npm/semver?current=7.5.0&releaseNotes=1