API catalog generator
An agent landing on your homepage cannot find an API documented only on a subdomain. This file is the one-fetch pointer — and one empty entry is worse than useless.
- Catalog is empty — no API entries survived trimming. C13 fails any linkset that advertises no API hyperlinks, so publishing this file is worse than useless: agents that fetch /.well-known/api-catalog are told the catalog exists but contains nothing, which is strictly worse than not publishing one at all.
{
"linkset": [
{}
]
}
Next steps
Save this as /.well-known/api-catalog (served as application/linkset+json;profile="https://www.rfc-editor.org/info/rfc9727"), then run an agent-readability scan to see C13 grade it.
Last updated
What is /.well-known/api-catalog?
/.well-known/api-catalog is an RFC 9264 linkset, standardised by RFC 9727 (published 2024), served at the well-known path. Instead of an agent guessing where your API descriptions live — a root /openapi.json probe only catches one convention — the catalog is a single fetch that lists every API your site exposes and points at each one’s machine-readable description via standard link relations. It is the catalog of catalogs: one document that tells an agent “here are all my APIs, and here is where each one’s contract lives”.
Why publish one?
Because an agent landing on your homepage cannot find an API documented only on a subdomain. Without a catalog, the agent has to guess — probe /openapi.json, scrape your docs for links, or give up. The catalog is the one-fetch pointer: the agent reads /.well-known/api-catalog and knows about every API you publish, including cross-origin ones an OpenAPI-at-root probe would miss. This exact gap is why our scanner’s C13 check exists — it fails a site that publishes no catalog, and it fails harder when a catalog exists but advertises nothing.
What goes in the linkset
The catalog is an RFC 9264 linkset — a JSON object with a linkset array. The first member is the catalog index: its anchor is the catalog’s own URL and its item list contains one entry per API. Each subsequent member describes a single API via three link relations:
anchor— the API’s URL (what the entry is about)service-desc— a link to the machine-readable description (OpenAPI, MCP card)service-doc— a link to human-readable documentation (optional)
{
"linkset": [
{
"anchor": "https://example.com/.well-known/api-catalog",
"item": [
{ "href": "https://example.com/api", "title": "Example API" }
]
},
{
"anchor": "https://example.com/api",
"service-desc": [
{ "href": "https://example.com/openapi.json", "type": "application/openapi+json;version=3.1" }
],
"service-doc": [
{ "href": "https://example.com/docs/api" }
]
}
]
}The serve contract
Serve the file at /.well-known/api-catalog with Content-Type application/linkset+json;profile="https://www.rfc-editor.org/info/rfc9727". RFC 9727 §4 requires the linkset+json media type; the profile parameter names the RFC the document conforms to. Serving it as plain application/json will still parse, but C13 flags it as a content-type degradation — the linkset is valid but the agent cannot confirm it is an RFC 9727 catalog without the media type.
Frequently asked questions
- What is /.well-known/api-catalog?
- It is an RFC 9264 linkset, standardised by RFC 9727, served at /.well-known/api-catalog. Instead of an agent guessing where your API descriptions live (a root /openapi.json probe only catches one convention), the catalog is a single fetch that lists every API your site exposes and points at each one’s machine-readable description — OpenAPI, an MCP server card, or an A2A agent card — via standard link relations.
- How is the API catalog different from agents.json or an OpenAPI spec at the root?
- An OpenAPI document describes one API’s operations. agents.json maps a REST API’s endpoints to agent-callable actions. The API catalog is broader: it is an index of every API the site publishes, cross-origin ones included, with each entry pointing at its own description document. An agent landing on your homepage fetches the catalog once and knows about every API — the OpenAPI at /api/v1/openapi.json, the MCP server at /.well-known/mcp.json, and the A2A endpoint at /.well-known/agent-card.json — without crawling or guessing.
- What link relations does RFC 9727 use?
- The catalog is an RFC 9264 linkset. The first member is the catalog index: its anchor is the catalog’s own URL and its item list contains one entry per API (href + title). Each subsequent member describes a single API: its anchor is the API’s URL, and it carries service-desc (a link to the machine-readable description, e.g. an OpenAPI document) and optionally service-doc (a link to human-readable documentation). RFC 9727 requires these relations to contain real hyperlinks, not placeholders.
- What Content-Type should I serve the catalog as?
- Serve it as application/linkset+json with the RFC 9727 profile parameter: application/linkset+json;profile="https://www.rfc-editor.org/info/rfc9727". RFC 9727 §4 requires the linkset+json media type; the profile parameter is the canonical, recommended form that names the profile the document conforms to. Serving it as plain application/json will still parse, but our scanner’s C13 check flags it as a content-type degradation.
- What happens if I publish an empty catalog?
- An empty catalog is worse than not publishing one. An agent that fetches /.well-known/api-catalog and gets a 200 with a linkset that advertises no API hyperlinks has been told the catalog exists but contains nothing — it cannot fall back to guessing, because the site has explicitly declared it has no APIs to index. Our scanner’s C13 check fails a linkset that advertises no item, service-desc, or service-doc hyperlinks. The generator warns about this before you publish.
- Why does the generator ask for my site URL?
- To seed the catalog with entries that verifiably exist. The generator probes your site’s real manifests (/openapi.json and friends, /.well-known/mcp.json, /.well-known/agent-card.json) and only offers entries it just fetched — it never invents an anchor or a service-desc URL. A catalog that points at a manifest your site doesn’t serve is a broken pointer that sends the agent back to scraping your docs; the detection step closes that loop.
- Where do I put the file?
- Serve it at /.well-known/api-catalog with the Content-Type application/linkset+json;profile="https://www.rfc-editor.org/info/rfc9727". Optionally, advertise it from your homepage with a Link: rel="api-catalog" HTTP header so an agent can discover it from a HEAD request without parsing the HTML body. After publishing, run an agent-readability scan to confirm C13 grades the live file as a pass.