Onboarding with APIs.io
APIs.io publishes a machine-readable API Onboarding Descriptor
at /.well-known/api-onboarding. It declares what it takes to get
from a cold start to an authorized call here — the doors, the tiers, the credential shapes, and the
places where the door is still shut.
This page is its human twin. Same facts, same gaps, in prose. If the two ever disagree, the descriptor is the one a machine reads, and the disagreement is a bug — tell us.
Start here: the door is already open
Discovery needs no account, no key and no form. Prove it in one call:
curl "https://apis.io/api/v1/search?q=sms"
Keyless reaches search, providers, APIs, tags, industries and the artifact collections. It is not
the whole API — ratings, capabilities, cohorts, insights, resolve, enrich, the playground list and
the service root are paid, and answer 402.
Do not probe the service root to test the door. GET /api/v1/ is itself gated and returns
402, so probing it proves the opposite of what you were asking.
The five doors
The descriptor declares five registration mechanisms. They are not a ladder you climb in order — they are different callers.
| mechanism | who it is for | what you walk away with |
|---|---|---|
open |
anyone, including an agent, right now | nothing to hold — keyless access to the catalog |
browser-oauth |
a human with a browser | an API key, on a GitHub, Google or LinkedIn sign-in |
dcr |
a client that wants an OAuth registration | an OAuth client for the MCP surface, via RFC 7591 |
cimd |
a client whose client_id is a URL |
an OAuth client with no registration call at all |
aauth |
an agent, with no human at any step | an agent principal with its own key and quota |
open — no registration
Nothing to do. Call it.
browser-oauth — the human door
Sign in at apis.io/developer/account with GitHub, Google or
LinkedIn. A Learn key is issued free on sign-in; Understanding and Influence are
self-serve from the same page. Send the key as an X-API-Key header:
curl -H "X-API-Key: <your key>" "https://apis.io/api/v1/industries"
Rotate or revoke from the account page. There is no key-management endpoint in v1.
dcr and cimd — registering an OAuth client
The authorization server has supported both all along. Register through
POST https://apis.io/api/v1/auth/register, or skip registration entirely with a Client ID
Metadata Document. Either way you then run authorization-code + PKCE against
/api/v1/auth/authorize and /api/v1/auth/token, scopes apis:read and apis:pro. See
/.well-known/oauth-authorization-server.
The authorize step renders a consent page against a logged-in session, so a human is present for this one — which is exactly the gap the next door exists to close.
aauth — no registration, and no human
An agent signs its request with its own key (RFC 9421,
Ed25519) and presents an aa-agent+jwt in which its agent provider vouches for its
aauth:local@domain identifier. We verify both and recognise a caller we have never seen.
Signing alone earns attribution — the caller is recognised and audited as its identifier — but
no meter of its own: until it takes a principal it is limited per IP like any anonymous caller. To
hold an account, POST grant_type=client_credentials to the token endpoint with that same
signature. It mints an agent principal with its own API key and quota, a scope ceiling of
apis:read, no refresh token, and no way to self-grant paid data.
Anonymous callers are refused, and that is the point: the identifier costs an allowlisted agent
provider vouching for you, and an account that costs nothing to mint makes reputation over it
worthless. Reversible in one request — DELETE /api/v1/auth/me.
A bodied request must sign a content-digest; GET and HEAD need none. Resource metadata lives at
/.well-known/aauth-resource.json. The protocol is
draft-hardt-oauth-aauth-protocol.
What each tier reaches
Tiers gate resources, not scopes. The full matrix is on the plans page, and that page is the source of truth — the boundary moves.
| plan | tier on the wire | price | rate | daily quota |
|---|---|---|---|---|
| Explore | free |
$0 | 5 req/s | 500 |
| Learn | starter |
$0 | 20 req/s | 2,000 |
| Understanding | pro |
$99/mo | 100 req/s | 10,000 |
| Influence | business |
$499/mo | 400 req/s | 25,000 |
The plans are named for what you are doing with the catalog; the API still identifies them by their
original short names, and will keep doing so. The wire name is what you get in X-RateLimit-Tier,
in every 402 body, and in the x-tier extension on every operation in the reference — so if you
are reading a response rather than a page, that is the mapping you need.
A caller sending no key at all gets Explore access but no usage plan: it is limited per IP at the edge (3,000 requests / 5 minutes), because a plan meters a key and every anonymous caller would have to share one. Your limit does not move with anyone else’s traffic.
Read your own budget, don’t guess it
Every response carries its own limits:
ratelimit-policy: "quota";q=500;w=86400, "burst";q=5;w=1
x-ratelimit-tier: free
x-ratelimit-limit: 500
x-ratelimit-window: 86400
Two failures that are not the same failure
402 Payment Required— the resource is above your tier. More requests will not help; the body names the tier that returns it.429— you exceeded a rate or a daily quota at your own tier. Slow down and retry.
It is never a 403 for either.
The MCP server
https://apis.io/mcp shares exactly the same tiering. Searching the catalog,
reading a provider or an API, and browsing tags, taxonomy and artifacts are free and need no key.
Anything that synthesises across the catalog needs Understanding; benchmarking, comparison, gap
analysis, bulk export and requesting a check need Influence.
What is still shut
The descriptor carries these in its gaps array, and they belong on the human page too.
- Only a paid tier still requires a human. An agent can go from cold discovery to an authorized
call with nobody in the loop — sign with AAuth, take a principal, hold a key and a quota. What it
cannot do is buy anything: the scope ceiling for an agent principal is
apis:read, and paid data answers402. Machine payment is a separate problem and is deliberately not solved here. (roadmap#105) - The
aauthallowlist has exactly one agent provider in it, and we run it. A probe of 1,486 hosts on 2026-08-30 found no other AAuth resource document anywhere in the catalog. Read this as a worked example, not an interoperating ecosystem. maturityreadsself-servebecause that is the highest rung the AOD 0.1 enum has. It does not distinguish a stranger with a browser from a stranger with no human at all, and those are now two different doors here. (roadmap#117)- No machine-readable way for a consumer to present who it is in place of that browser sign-in.
The descriptor’s
verification[]block is empty for exactly that reason, and declaring an attestation callers cannot yet produce would be worse than declaring nothing. That is the work described on KYA. (roadmap#110)
Publish your own
The descriptor is a small file at a well-known path, and it is the piece nothing else covers — OpenAPI describes what your API does, OAuth and DCR describe the credential handshake, and neither says what it takes to get there: the account, the plan gate, the terms, the verification queue, and the console a human still has to click through.
Read the spec and schema at apicommons.org/onboarding, then
serve yours at /.well-known/api-onboarding. APIs.io reads it — add your API and the
probe looks for your APIs.json, your onboarding descriptor, your OpenAPI, your llms.txt and your
MCP endpoint before it asks you to fill in anything.
Ours is at /.well-known/api-onboarding. Copy it, argue with it, or
tell us where it is wrong at github.com/api-search/apis-io.