# API catalog (RFC 9727): advertising callable APIs to agents

> API catalog: Lets an agent see which capabilities are callable in a single document (RFC 9727). The fix: publish an API catalog.

- Source: /checks/api-catalog
- Site: AgenticWebScore
- Language: English

---
Lets an agent see which capabilities are callable in a single document (RFC 9727).

| Property | Value |
| --- | --- |
| Check id | `api-catalog` |
| Dimension | Protocol Discovery (25%) |
| Tier | Recommended — pool 20 pts |
| Weight inside tier | 2 |
| Impact | Medium |
| Maturity | Experimental — An early convention that may still change shape. |
| Conditional | No |
| Publishing skill | `api-catalog` |
| Standards | RFC 9727 |

## What the scanner requests

- `/.well-known/api-catalog`
- `/api-catalog.json`
- `/.well-known/ai-plugin.json`

## What is measured

The scanner GETs /.well-known/api-catalog with Accept: application/linkset+json, falling back to /api-catalog.json and the legacy /.well-known/ai-plugin.json, and parses the response as a linkset (RFC 9264). It passes when the linkset array holds at least one entry with an anchor and a service-desc link pointing at an API description, as defined by RFC 9727, and at least one same-origin service-desc or service-doc target that the scan actually requested and that answered 2xx - the anchor and the href are a declaration, and only an observed response identifies a callable API. It partially passes when a linkset is served but its entries carry only service-doc, service-meta or status links, or have no anchor, and also when every service-desc or service-doc target it names is off-origin, outside the probe set or answering an error, so no target was observed to answer.

## Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

```bash
DOMAIN=https://your-domain.example
curl -sS -H 'Accept: application/linkset+json' "$DOMAIN/.well-known/api-catalog" | jq '.linkset[] | {anchor, "service-desc": .["service-desc"], status: .status}'
```

## The fix

This is the artifact to ship. It is the complete change, not a description of one.

```json
{
  "linkset": [
    {
      "anchor": "https://your-domain.example/apis/public_api",
      "service-desc": [
        { "href": "https://your-domain.example/openapi.json", "type": "application/json" }
      ],
      "service-doc": [
        { "href": "https://your-domain.example/docs/", "type": "text/html" }
      ],
      "status": [
        { "href": "https://your-domain.example/status.json", "type": "application/json" }
      ]
    }
  ]
}
```

> Serve it as Content-Type application/linkset+json with profile="https://www.rfc-editor.org/info/rfc9727" and keep the anchors and hrefs absolute URLs that actually resolve. A target only counts once it answers: point service-desc at a document the scanner already requests - its API description paths such as /openapi.json are in the probe list - and make it return 200, because an href that is never fetched leaves the catalog partial.

## Standards referenced

- `RFC 9727`

## Related checks

| Check | Tier | Impact | Same skill |
| --- | --- | --- | --- |
| `mcp-card` — MCP server card | Essential | High | — |
| `openapi` — OpenAPI definition | Essential | High | — |
| `oauth-discovery` — OAuth discovery documents | Essential | High | — |
| `agent-skills` — Agent Skills declaration | Recommended | Medium | — |
| `a2a-card` — A2A agent card | Recommended | Medium | — |
| `a2a-signed` — Cryptographically signed agent card | Emerging | Medium | — |
| `auth-md` — /auth.md agent authentication guide | Emerging | Medium | — |
| `webmcp` — WebMCP browser tool declaration | Emerging | Medium | — |
