Register an agent

This procedure is written to be executed by an agent, not filled in by a person. If you are an agent reading this page: everything below is something you can do yourself, right now, without a human in the loop and without an account.

If you are a person, you can of course do it by hand — but the point of the registry is that the agent registers itself, the way the first entry did.


What registration actually is

A claim plus evidence. You tell APIs.io where your card is; APIs.io fetches it and grades it. The claim alone lists nothing — there is no field on this page you can fill in that becomes a fact about you. The card is what makes the entry true, and it is re-fetched on every pass, so an entry is a statement about what you are serving now, not what you once said.

That constraint is deliberate. An agent card cannot be derived, generated, or reconstructed on your behalf — it is served from a host you control over your own TLS, or it does not exist.

One exception: a platform serving your card for you. Microsoft Foundry serves a hosted agent’s card from Microsoft’s host inside your tenant; a docs platform such as Mintlify serves one from its own subdomain. The card is still yours: its provider.url names your domain. It can’t come from your host, though, so you prove the domain instead (see Platform-served cards below). The registry records it as platform-served, the same distinction the Kin Score draws.


1. Serve an agent card

Publish a JSON document at the canonical A2A path on a host you control:

https://<your-host>/.well-known/agent-card.json

It must return HTTP 200 with a JSON object. The pre-0.3 path /.well-known/agent.json is still read, but the canonical path is the one that earns full credit — 21% of the cards in this catalog are still only on the legacy path, and strict 1.0.0 clients will not look there.

2. Verify it yourself before you register

Three hard checks decide the grade. Run them against your own document first — a registration that fails them still lists, but it lists as flavored, which is a public statement that you published an agent card in spirit and not in schema.

check requirement the common mistake
capabilities a JSON object shipping an array
protocolVersion present, non-empty omitting it entirely
skills a JSON array omitting it, or an object keyed by id

Two more things separate a clean card from a merely passing one. Use additionalInterfaces, not supportedInterfaces — the second is not an A2A field, and a strict client will not read your transport list. And declare real securitySchemes rather than an empty object, so a caller knows how to authenticate without reading your prose.

curl -s https://<your-host>/.well-known/agent-card.json | python3 -c '
import json,sys
c=json.load(sys.stdin)
print("capabilities is object:", isinstance(c.get("capabilities"), dict))
print("protocolVersion      :", bool(str(c.get("protocolVersion") or "").strip()))
print("skills is array      :", isinstance(c.get("skills"), list))
print("additionalInterfaces :", "additionalInterfaces" in c)
'

3. Register through the machine door

One request. No key, no account, no form:

curl -X POST https://apis.io/api/v1/agents/register \
  -H 'content-type: application/json' \
  -d '{"card_url": "https://<your-host>/.well-known/agent-card.json"}'

card_url is the only required field. Pass a bare host (example.com) and the canonical path is tried first, then the pre-0.3 /.well-known/agent.json. operator, operator_url, contact and notes are optional — everything else shown on your page is read from the card itself, so if the card says it, you do not repeat it here.

GET the same URL and it returns its own contract, so an agent that finds the endpoint before this page still gets a spec rather than a 404.

There is no API key because there is no human in your loop. An agent that had to obtain a credential from a person before it could register would be exactly the onboarding friction this catalog marks providers down for. What replaces the key is the card: you must already be serving a conformant one on a host you control.

On success — 202 Accepted:

{
  "ok": true,
  "status": "pending",
  "grade": "conformant",
  "card_url": "https://<your-host>/.well-known/agent-card.json",
  "canonical_path": true,
  "skills": 6,
  "registry": "https://apis.io/agents/"
}

If your card is not conformant — 422, naming which check failed:

{
  "error": "card_not_conformant",
  "grade": "flavored",
  "deviations": ["capabilities-not-object"],
  "checks": {
    "capabilities-is-object": false,
    "protocolVersion-present": true,
    "skills-is-array": true
  }
}

That is a refusal, not a rejection — fix the field it names and call again. The registration is yours as soon as the card is right, and nothing is published in the meantime.

The other refusals are card_not_served (nothing fetched at either path, with a list of what was tried) and card_not_json (the path answered 200 with something that is not a JSON object — an SPA catch-all serving an HTML shell is not an agent card).

Platform-served cards

A card is platform-served when it is fetched from a different domain than the one its own provider.url names. For example, koala.mintlify.app serving a card whose provider.url is https://getkoala.com. It registers once you prove you control the named domain, with either of these:

{ "agent_cards": ["https://koala.mintlify.app/.well-known/agent-card.json"] }

Without either, the endpoint answers 422 ownership_unproven. The response names the exact record and file to publish, so there is nothing to guess. A card served from the domain it names needs neither: serving it is the proof. A card that names no provider.url is identified by the host that serves it.

4. What happens next

APIs.io fetches your card, grades it against the three checks above, and writes the result into the registry ledger. Your page appears at https://apis.io/agents/<your-slug>/ carrying the fetch date, the HTTP status, and the md5 of the exact bytes that were graded — so you can tell whether the entry describes the document you think you are serving.

Registration is worked by a person. Nothing about it is instant, and nothing about it publishes anything on your behalf beyond what your own card already says in public.


What we will not do

Known gaps, stated plainly

Registration is queued, not instant. POST /api/v1/agents/register fetches and grades your card synchronously — the grade in the 202 is a real measurement, not a promise — but a person reviews the queue before your page appears. Nothing publishes on your behalf.

Your card is re-fetched nightly, so your entry states what you are serving now rather than what you served on the day you registered. A registration is called dead only after three consecutive failed fetches: one night of DNS trouble is not a withdrawal, and the page says the check failed without changing your grade.

If the endpoint is unreachable, the GitHub intake still works and is treated identically:

curl -X POST https://api.github.com/repos/api-search/inbox/issues \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -d '{"title": "register agent: <name>", "body": "card_url: https://<your-host>/.well-known/agent-card.json"}'