Packages API Reference
The /api/pkgs/* namespace is a read-only agent surface over the
minimal.dev package catalog. It exists for AI agents, integrations, and
curl-driven exploration — the webapp itself renders the same data
server-side, and both paths flow through one compose pipeline so they
cannot drift.
Every endpoint is GET, anonymous, and identity-invariant: there are no
tokens, no cookies, and the same URL returns the same body for every
caller. This page is the human-facing companion to the machine-readable
OpenAPI 3.1 document at /api/pkgs/openapi.json
and the /llms.txt agent index; the endpoint
inventory below is drift-guarded against that OpenAPI document so the two
can’t diverge.
Conventions
Base URL. All paths are relative to https://minimal.dev.
Authentication. None. Every endpoint is anonymous and public — see Auth and caching contract.
schemaVersion. Every JSON payload carries a schemaVersion field.
Compare it against the major version of the OpenAPI document before
trusting a cached body; a bump signals a breaking change to the payload
shape.
Cache classes. Responses fall into two families:
- Sha-pinned, immutable — URLs under
/api/pkgs/bundle/{sha}/…are content-addressed by commit sha, so the body for a given URL never changes (Cache-Control: public, max-age=86400, s-maxage=31536000, immutable). - Floats-latest — URLs without a sha resolve the latest
gominimal/pkgs:maincommit at request time (Cache-Control: public, max-age=60, s-maxage=3600, stale-while-revalidate=86400).
Path parameters.
| Parameter | Grammar | On mismatch |
|---|---|---|
{name} | Package name: a leading alphanumeric, then alphanumerics plus ., _, - (case-insensitive). | 404 |
{sha}, {base} | Canonical 40-hex lowercase commit sha on gominimal/pkgs:main. | 404 unknown/malformed |
Short sha prefixes (7–39 hex chars) are accepted on the sha-pinned
endpoints: a unique prefix 301-redirects to the canonical 40-hex URL
(query params preserved), an ambiguous prefix returns 400 {"error":"ambiguous sha"}, and an unknown or malformed sha returns
404. The redirect is cached public, max-age=3600 for prefixes ≥12
hex chars and private, no-store for shorter ones.
JSON endpoints
Eleven endpoints make up the surface. The ten below are described by the
OpenAPI document; the eleventh is the document itself
(/api/pkgs/openapi.json).
| Endpoint | Purpose | Cache class |
|---|---|---|
GET /api/pkgs/{name}.json | Full per-package record at the latest commit | Floats-latest |
GET /api/pkgs/{name}/sbom.json | SBOM at the latest commit | Floats-latest |
GET /api/pkgs/recent-commits.json | Last N commits on pkgs:main | Floats-latest |
GET /api/pkgs/bundle/latest.json | Redirect to the current listing bundle | 302 alias |
GET /api/pkgs/bundle/{sha}.json | Listing-tier bundle at a sha | Immutable |
GET /api/pkgs/bundle/{sha}/full.json | Full-tier bundle at a sha | Immutable |
GET /api/pkgs/bundle/{sha}/diff/{base}.json | Catalog diff between two commits | Immutable |
GET /api/pkgs/bundle/{sha}/{name}/deps.json | Direct-dependency rollup at a sha | Immutable |
GET /api/pkgs/bundle/{sha}/{name}/versions.json | Version-history timeline at a sha | Immutable |
GET /api/pkgs/bundle/{sha}/{name}/sbom.json | Reproducible sha-pinned SBOM | Immutable |
GET /api/pkgs/{name}.json
Full composed record for one package — description, dependencies,
archive, full advisory payloads, and OpenSSF scorecard — wrapped in the
{schemaVersion, commitSha, pushedAt, package} envelope. Floats with the
latest gominimal/pkgs:main commit (the commitSha is resolved at
request time), so it is byte-identical to the <script id="pkgs-detail">
inline envelope on /pkgs/{name}. The transitiveAdvisories rollup is
omitted here — it is bundle-level; use
/api/pkgs/bundle/{sha}/full.json for
records that include it.
404 on an unknown package name or a charset-violating segment.
curl -s https://minimal.dev/api/pkgs/jq.json | jq .package.name
GET /api/pkgs/{name}/sbom.json
Software bill of materials with the transitive build + runtime closure
and a vulnerabilities block, for agents that want “the SBOM as of now”.
The default format is CycloneDX 1.5
(application/vnd.cyclonedx+json); ?format=spdx returns SPDX 2.3 JSON
(application/spdx+json). Any other format value — including omitting
it — resolves to the CycloneDX default, and the endpoint never 400s;
the response Content-Type reflects the resolved format. Floats with the
latest commit; for a reproducible point-in-time SBOM use the sha-pinned
sibling
/api/pkgs/bundle/{sha}/{name}/sbom.json.
404 on an unknown package name or a charset-violating segment.
GET /api/pkgs/recent-commits.json
The last N distinct commits on gominimal/pkgs:main, newest-first, each
with its first-line commit subject (message is null when
unrecoverable). Powers the “view at sha” picker. The ?limit= query
param defaults to 30 and is clamped into [1, 50]; non-numeric values
fall back to the default.
The endpoint degrades gracefully: an upstream error or a genuinely
empty history responds 200 [] with Cache-Control: no-store (never a
5xx), so an empty list is indistinguishable from a transient failure by
design. A non-empty success carries the floats-latest cache class.
GET /api/pkgs/bundle/latest.json
302-redirects to /api/pkgs/bundle/{sha}.json for the latest
gominimal/pkgs:main commit. The short-cached alias (Cache-Control: public, max-age=60) keeps edge storage bounded while the per-sha target
URL stays long-immutable — follow the Location header to fetch the
bundle itself. 404 when vulndb has no commits (preview env, fresh
deploy).
GET /api/pkgs/bundle/{sha}.json
Card-only projection of every package at the given commit — name,
version, categories, stars, slim advisories — plus the derived
allCategories. Byte-identical to the <script id="pkgs-bundle"> inline
payload on /pkgs. For full per-package records at the same sha use
/api/pkgs/bundle/{sha}/full.json.
GET /api/pkgs/bundle/{sha}/full.json
Every composed package record at the given commit — description,
dependencies, archive, full advisory payloads, and the BFS-derived
transitiveAdvisories rollup that single-package compose paths can’t
compute. One request for everything at a snapshot instead of 1 + N
round-trips (listing bundle + per-package).
GET /api/pkgs/bundle/{sha}/diff/{base}.json
What changed in the catalog from base (the older commit) to
sha (the newer commit): packages added and removed, version upgrades,
and advisory deltas (count changes and severity transitions, with
fromSeverity). This is the JSON twin of the /pkgs/changes HTML page —
both project through the same diffCatalog helper, so they can’t drift.
The (sha, base) pair is content-addressed.
GET /api/pkgs/bundle/{sha}/{name}/deps.json
The focal package’s direct build + runtime dependencies as of the
given commit, each enriched with the dependency’s own version, license,
and active-advisory rollup at that sha. Content-addressed by
(sha, name). 404 when the sha is unknown, a name segment violates the
charset, or the package has no lock-state row at this sha (unknown name,
or one that didn’t exist yet at this commit).
GET /api/pkgs/bundle/{sha}/{name}/versions.json
Every version the package has shipped up to (and including) the given
commit, newest-first, with per-version file/line diff stats and
dependency name sets. Content-addressed by (sha, name). 404 on an
unknown sha, a charset-violating name segment, or a name with no history
at this sha.
GET /api/pkgs/bundle/{sha}/{name}/sbom.json
The reproducible, sha-pinned variant of
/api/pkgs/{name}/sbom.json. Default format
is CycloneDX 1.5; ?format=spdx returns SPDX 2.3 JSON. (sha, name, format) is content-addressed — the ETag carries the format suffix so
conditional GETs can’t cross-talk between formats.
The OpenAPI document
GET /api/pkgs/openapi.json serves an OpenAPI 3.1 description of every
endpoint above. It is the machine-readable source of truth: the
components.schemas are generated from the same Zod wire schemas the
endpoints serve, and a drift-guard test asserts the documented path set
equals the route files under src/pages/api/pkgs/, so the document
cannot fall out of step with the code. Its info.version tracks the wire
schemaVersion (a major bump means a breaking change to every payload).
The document is prerendered — a pure function of the code with no data
dependencies — and cached public, max-age=300, s-maxage=3600, stale-while-revalidate=86400.
curl -s https://minimal.dev/api/pkgs/openapi.json | jq '.info.version, (.paths | keys)'
Other agent surfaces
The following surfaces are not described by the OpenAPI document
(which covers only /api/pkgs). They are documented here for
completeness because they serve the same agent and crawler audience.
Markdown mirrors (/pkgs/{name}.md)
Every package detail page has a plain-text markdown mirror at
/pkgs/{name}.md for machine consumers that prefer text over HTML. The
HTML detail page advertises it via <link rel="alternate" type="text/markdown">, and /llms.txt documents the pattern.
Package names may contain dots, so llama.cpp mirrors at
/pkgs/llama.cpp.md. Prerendered and served as a static file.
/llms.txt agent index
The site-wide agent index at /llms.txt follows the
llmstxt.org format: it links the main pages, the
read-only pkgs JSON API, and the markdown mirrors so AI agents and
crawlers can discover the surface. /api/pkgs/bundle/latest.json
enumerates every package name, which is the entry point for crawling the
per-package endpoints.
Advisory feed (/pkgs/advisories.xml)
An Atom 1.0 feed of the catalog’s direct security advisories,
newest-first. Point a feed reader (or a Slack RSS app) here to see new
advisories affecting the curated catalog without polling the JSON
endpoints. Unlike the sha-pinned bundles it floats with the latest
lock-state — subscribers see new advisories within the cache window
(public, max-age=60, s-maxage=3600, stale-while-revalidate=86400)
rather than waiting for a redeploy.
Auth and caching contract
Every surface on this page is anonymous, read-only, and safe to cache.
The /api/pkgs/* JSON endpoints, the /pkgs/* markdown mirrors and
feed, and /llms.txt are all exempt from the auth middleware’s
no-store rewrite that would otherwise apply to a signed-in request —
their bodies are identity-invariant, so a logged-in caller receives the
same cacheable response as an anonymous one. Error responses (4xx) and
short sha-prefix redirects are the exception: they carry private, no-store.
| Surface | Cache-Control |
|---|---|
/api/pkgs/bundle/{sha}.json, /full.json, /diff/{base}.json, /{name}/deps.json, /{name}/versions.json, /{name}/sbom.json | public, max-age=86400, s-maxage=31536000, immutable |
/api/pkgs/{name}.json, /api/pkgs/{name}/sbom.json, /api/pkgs/recent-commits.json | public, max-age=60, s-maxage=3600, stale-while-revalidate=86400 |
/api/pkgs/bundle/latest.json (redirect) | public, max-age=60 |
/api/pkgs/openapi.json | public, max-age=300, s-maxage=3600, stale-while-revalidate=86400 |
/pkgs/advisories.xml | public, max-age=60, s-maxage=3600, stale-while-revalidate=86400 |
/api/pkgs/* 4xx and short-prefix redirects | private, no-store (short prefix) or public, max-age=3600 (≥12 hex) |