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:main commit at request time (Cache-Control: public, max-age=60, s-maxage=3600, stale-while-revalidate=86400).

Path parameters.

ParameterGrammarOn 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).

EndpointPurposeCache class
GET /api/pkgs/{name}.jsonFull per-package record at the latest commitFloats-latest
GET /api/pkgs/{name}/sbom.jsonSBOM at the latest commitFloats-latest
GET /api/pkgs/recent-commits.jsonLast N commits on pkgs:mainFloats-latest
GET /api/pkgs/bundle/latest.jsonRedirect to the current listing bundle302 alias
GET /api/pkgs/bundle/{sha}.jsonListing-tier bundle at a shaImmutable
GET /api/pkgs/bundle/{sha}/full.jsonFull-tier bundle at a shaImmutable
GET /api/pkgs/bundle/{sha}/diff/{base}.jsonCatalog diff between two commitsImmutable
GET /api/pkgs/bundle/{sha}/{name}/deps.jsonDirect-dependency rollup at a shaImmutable
GET /api/pkgs/bundle/{sha}/{name}/versions.jsonVersion-history timeline at a shaImmutable
GET /api/pkgs/bundle/{sha}/{name}/sbom.jsonReproducible sha-pinned SBOMImmutable

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.

SurfaceCache-Control
/api/pkgs/bundle/{sha}.json, /full.json, /diff/{base}.json, /{name}/deps.json, /{name}/versions.json, /{name}/sbom.jsonpublic, max-age=86400, s-maxage=31536000, immutable
/api/pkgs/{name}.json, /api/pkgs/{name}/sbom.json, /api/pkgs/recent-commits.jsonpublic, max-age=60, s-maxage=3600, stale-while-revalidate=86400
/api/pkgs/bundle/latest.json (redirect)public, max-age=60
/api/pkgs/openapi.jsonpublic, max-age=300, s-maxage=3600, stale-while-revalidate=86400
/pkgs/advisories.xmlpublic, max-age=60, s-maxage=3600, stale-while-revalidate=86400
/api/pkgs/* 4xx and short-prefix redirectsprivate, no-store (short prefix) or public, max-age=3600 (≥12 hex)