An agent that signs up for your API should arrive with a record.
An AI agent can't fill in a signup form, and the form was never really about authentication. It was how a provider found out who it was dealing with. APIs.io already tells agents which APIs exist. KYA is how it also tells providers which agents are knocking.
Finds APIs in the catalog, signs up to them, and carries its record when it does.
The person or company answerable for the agent. They disclose facts about it once.
The catalog, the router between agents and providers, and the registry that checks the facts.
Reads the record under its own priorities and decides what access to grant.
Eight steps from registry to credentials
Step through it, or click any arrow. Each step says whether APIs.io runs it today or it is the provider's own call.
Facts with grades, not a trust verdict
The consumer record mirrors the six facets of the provider Kin Score. Every fact carries a grade that says how we know it, and the grade travels with the fact.
| Facet | KYC analogue | What it asks | Example checks |
|---|---|---|---|
| Identity Anchor | identity document | Is this caller tied to something it can't mint again for free? Every other facet is worth less without it. | web_bot_auth_verified · cimd_served · domain_control · workload_identity |
| Operator Accountability | beneficial owner | Who answers for it, and can they be reached when something goes wrong? | operator_email · abuse_contact · legal_entity · published_terms |
| Provenance & Attestation | source of applicant | What is the agent built from, and can any of that be checked? | source_repository · signed_releases · attestation_evidence |
| Declared Intent | purpose of relationship | What did it say it would do, and does its behaviour match? | stated_purpose · scope_discipline · crawl_preferences_respected |
| Operating History | ongoing monitoring | What has it actually done over time? A new agent can't have this yet, and being new isn't suspicious. | tenure · incident_history · multi_provider_presence |
| Standing | source of funds | Is there a commercial relationship, and does it behave? This facet is last on purpose. KYA is not a credit check. | paid_relationship · x402_capable · quota_compliance |
The record carries two numbers, never one. Disclosure measures how much the agent has told us, and the agent controls it. Verification measures how much of that we confirmed independently, and the agent doesn't control it. If the two were merged into one number, an agent could look trustworthy just by filling in more fields. The full vocabulary is open at GET /api/v1/kya/rubric, no key needed.
One agent, three providers, three answers
A documentation search API and a payments API should not reach the same decision about the same agent. Each provider weights the facets by its own priorities and sets its own minimums. Change the agent's grades and watch each decision move.
An example agent, simplified to one grade per facet. The real record grades 26 checks.
The provider makes the decision. APIs.io returns the weighted result and a list of what's missing, ranked by what each item would add. An agent that's turned away gets a to-do list instead of a flat no.
One signed attestation in three standard places
A header that only says "I came from APIs.io" proves nothing, because anyone can type it. The identifier that matters is a short-lived attestation signed by APIs.io and bound to the agent's own key. A copied attestation is useless without the private key that goes with it.
// header: {"alg":"RS256","typ":"kya+jwt","kid":"…"} { "iss": "https://apis.io", "sub": "aauth:agent@example.com", "aud": "https://api.provider.example", "iat": 1791072000, "exp": 1791072600, "jti": "6f1c…", "cnf": { "jkt": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" }, "binding": "key", "kya": { "record": "https://apis.io/api/v1/agents/aauth:agent@example.com", "tier": "anchored", "disclosure": 0.714, "verification": 0.583, "rubric": "0.1" }, "agent": { "slug": "example", "card": "https://example.com/.well-known/agent-card.json" } }
cnf.jkt pins it to the agent's signing key. The provider checks it against https://apis.io/.well-known/jwks.json and refuses any typ other than kya+jwt.# 1. OAuth providers: RFC 7591 software statement POST /oauth/register HTTP/1.1 Host: api.provider.example Content-Type: application/json { "client_name": "Example Agent", "grant_types": ["client_credentials"], "software_statement": "eyJhbGciOiJSUzI1NiIsInR5cCI6Imt5…" } # 2. Any HTTP signup: signed request (RFC 9421 / Web Bot Auth) POST /v1/signup HTTP/1.1 Host: api.provider.example APIs-IO-Attestation: eyJhbGciOiJSUzI1NiIsInR5cCI6Imt5… Signature-Agent: sig1="https://example.com" Signature-Input: sig1=("@method" "@authority" "@path" \ "apis-io-attestation" "signature-agent");created=1791072000;\ keyid="NzbLsXh8…";tag="web-bot-auth" Signature: sig1=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp…: # 3. Token exchange (RFC 8693): the attestation as actor_token
# the provider asks for the full record, under its own weights POST /api/v1/agents/aauth:agent@example.com/evaluate HTTP/1.1 Host: apis.io Content-Type: application/json { "weights": { "identity_anchor": 3, "operator_accountability": 2, "standing": 2, "provenance_attestation": 0.5 } } HTTP/1.1 200 OK { "score": 0.64, "disclosure": 0.71, "verification": 0.58, "missing": [ { "facet": "standing", "check": "payment_verified", "grade": "absent", "reachable": "verified", "gain": 0.09 } ], "facts": { … } }
# the provider publishes what it requires, before any agent tries GET /.well-known/api-onboarding HTTP/1.1 Host: api.provider.example { "verification": [ { "facet": "domain_control", "min_grade": "verified", "blocking": true, "vocabulary": "https://apis.io/kya/" }, { "facet": "operator_email", "min_grade": "declared", "blocking": false } ], "x-kya-attestation-issuers": ["https://apis.io"] }
GET /api/v1/kya/match?provider=… reads it and tells the agent what it meets, what it's missing, and whether it can sign up now.Built from parts that already exist
Almost none of this is new. APIs.io's part is assembling the pieces and acting as the registry that grades the facts.
| Standard | Status | Role here |
|---|---|---|
| A2A Agent Card | Linux Foundation spec | The agent's self-description. Registering one is the way into the agent registry. |
| HTTP Message Signatures | RFC 9421 | Every signup request is signed, so an attestation can't be replayed by someone else. |
| Web Bot Auth | IETF WG draft, 2026 | The profile of RFC 9421 for automated clients: the Signature-Agent header plus a key directory at a well-known path. |
| OAuth Client ID Metadata Documents | IETF draft · MCP default | The agent's client ID is a URL it controls. MCP now prefers this over dynamic registration. |
| OAuth Dynamic Client Registration | RFC 7591 / 7592 | The software statement is the standard slot for a third party's signed claims about a client. UK Open Banking already works this way. |
| JWT access token profile | RFC 9068 | Why typ matters: an attestation is never accepted as an access token, here or anywhere that checks. |
| Protected Resource Metadata | RFC 9728 | Tells an agent which authorization server guards an API, so it can find the signup route. |
| Token Exchange, on-behalf-of drafts | RFC 8693 · IETF drafts | Carries the attestation as an actor_token when an agent acts for a person. |
| AAuth | Individual IETF draft | Per-agent keypairs and identifiers like aauth:local@domain. APIs.io speaks it, and it is what binds an attestation to a key. |
| API Onboarding Descriptor | API Commons 0.1 | Where a provider publishes what it requires from an agent, at /.well-known/api-onboarding. |
| KYAPay, Visa TAP, Akamai KYA | Commercial | Payment-network identity for agents. These can feed the record as evidence; they don't replace it. |
| x402 | Open protocol | Pay-per-call settlement, which counts toward the Standing facet. |
What each side does
If you run an agent
- Serve an A2A agent card and register it.
- Prove you control the domain with a DNS TXT record at
_apis-io-agent.<domain>. - Sign your requests with AAuth or Web Bot Auth, so your attestations are bound to your key.
- Disclose who runs the agent and what it's for with
PATCH /api/v1/kya/me. Disclosure is gradual, and an anonymous agent can still use the catalog. - Ask
/api/v1/kya/matchwhether you can join an API, thenPOST /api/v1/kya/attestand sign up.
If you run an API
- Publish
/.well-known/api-onboardingwith what you require from an agent. - Accept the APIs.io attestation as a software statement, or read it from the
APIs-IO-Attestationheader. - Verify it against the APIs.io key set, check
typ,audandexp, and check the request signature againstcnf.jkt. - Claim your listing, then call
evaluatewith your own weights. Reading a record is reciprocal: to see a consumer's facts, publish your own. - Report conduct back to
/api/v1/agents/{sub}/reports, always with the reason. That's where Operating History comes from.
What KYA is not
Who reads it
Not the public. The full profile goes to providers enrolled in the APIs.io network who maintain their own listing. This is reciprocity, on the UK Open Banking model: to see a consumer's facts, publish your own. Consumers see everything held about them, including which providers read their record and when, and every conduct report filed about them.
What APIs.io runs on top of these standards is a product, not a standard. There is no supervisory body here and no appeal beyond us. In their place: the rubric is public, every number can be recomputed, and correcting an error we made is free. Design and discussion happen in the open on the API Evangelist roadmap, and the vocabulary lives at API Commons. See the trust layer for how KYA fits with onboarding, authentication and payment.