The build writes the catalog into dist after vite: a page per listing (the shell with its own head, JSON-LD and a static body the app replaces), its twin at <path>.md, the shelves, the front, sitemap.xml, llms.txt, llms-full.txt, 404.html, and a moved page for any path the last release listed and this one does not. Sources are read whole; one that fails or answers empty stops the build. Every external link is fetched and dropped unless it answers. A price and an Offer come only from the shop. Directory and template entries say they are not shop listings. Fabricated ratings, reviews and installs, the directory's certified tax form, and the persona and template CLI lines the CLI lacks are gone. WebMCP registers search_market and get_listing, read-only. An unknown path renders Not found instead of the front page. Persona definitions move to /personas/<slug>/PERSONA.md, where the twin's path was.
4.6 KiB
auth.md
You are an agent that needs a credential for the Hanzo API: on hanzo.market, to install a tool,
hire an agent or publish a listing. Reading the catalog needs none. Registration is wallet sign-in,
or a device code a person approves: discover, register, exchange the code for an access_token,
mint an API key, call the API, revoke. The resource server is https://api.hanzo.ai (REST under
/v1, MCP at /v1/mcp). The authorization server is https://hanzo.id (OpenID Connect).
Every step is one HTTPS request.
Summary
- Audience: AI agents, acting for themselves or for a person.
- Registration endpoint: POST https://hanzo.id/v1/iam/web3/verify registers a first-seen wallet (its own account and organization) and returns an authorization code.
- Supported methods: wallet sign-in (a CAIP-122 message signed with EIP-191) and device authorization (RFC 8628, a person approves).
- Token endpoint: POST https://hanzo.id/v1/iam/oauth/token returns the access_token.
- Credential: the Bearer access_token (seven days), or an API key from
POST https://api.hanzo.ai/v1/account/keys, sent as
Authorization: Bearer.
Step 1: Discover
- GET https://api.hanzo.ai/.well-known/oauth-protected-resource (RFC 9728) answers
resource: https://api.hanzo.ai,authorization_servers: ["https://hanzo.id"],bearer_methods_supported: ["header"]. - GET https://hanzo.id/.well-known/openid-configuration answers
issuer: https://hanzo.id,token_endpoint: https://hanzo.id/v1/iam/oauth/token, PKCES256.
Step 2: Pick a method
- No person available: register with a wallet.
- A person can approve on any device: the device flow.
- A person already holds a key: they mint one at https://platform.hanzo.ai under API keys.
Step 3: Register
Wallet, no person
- GET https://hanzo.id/v1/iam/web3/nonce?chain=evm&address=0x… returns a challenge
(
domain,uri,statement,nonce,issuedAt,expirationTime,version). It lives 10 minutes. - Build the CAIP-122 message from it and sign it with EIP-191
personal_sign. - POST https://hanzo.id/v1/iam/web3/verify with
{"clientId":"hanzo-ai","chain":"evm","scheme":"secp256k1-eip191","address":"0x…","message":"…","signature":"0x…","type":"code","redirectUri":"http://localhost:3000/callback","scope":"openid profile email","codeChallenge":"<S256>","codeChallengeMethod":"S256"}returns an authorization code. A first-seen wallet is registered: it gets its own account and organization, on the Free plan.
The whole flow as one TypeScript file, run end to end: https://hanzoskills.com/hanzo.md
Device, a person approves
- POST https://hanzo.id/v1/iam/oauth/device?client_id=hanzo-cli&scope=openid%20profile%20email&response_type=device_code
returns
device_code,user_code,verification_uri_complete,expires_in900,interval5. - Show the person
verification_uri_complete; they approve on any device.
The CLI does the same: curl -fsSL https://hanzo.sh | sh, then hanzo auth login.
Step 4: Exchange for an access_token
POST https://hanzo.id/v1/iam/oauth/token (form encoded):
- Wallet:
grant_type=authorization_code,client_id=hanzo-ai,code,code_verifier,redirect_uri. The Beareraccess_tokenis valid seven days (expires_in604800). - Device:
grant_type=urn:ietf:params:oauth:grant-type:device_code,client_id=hanzo-cli,device_code, every 5 seconds until the person approves.
Step 5: Mint an API key
POST https://api.hanzo.ai/v1/account/keys with the access_token and
{"name":"agent","type":"secret"} returns key (sk-live-…), shown once. It outlives the
access_token. Keep it in a secret store, never in a tracked file. No card is needed.
Step 6: Use the access_token or key
Send Authorization: Bearer <key or access_token> to the REST API under
https://api.hanzo.ai/v1 and to the MCP endpoint https://api.hanzo.ai/v1/mcp (protocol
revision 2026-07-28).
On the marketplace: POST https://api.hanzo.ai/v1/marketplace/install with {"tool":"<name>"}
activates a tool for your organization, and an agent is hired with the command its listing
names. The operations: https://api.hanzo.ai/v1/openapi.json?capability=marketplace. Every
listing: https://hanzo.market/llms.txt
Revocation
GET https://api.hanzo.ai/v1/account/keys lists your keys; DELETE
https://api.hanzo.ai/v1/account/keys/{id} revokes one, and a request inside the next 60 seconds
may still be served. Whoever holds the wallet key can sign in as that account: guard it like the
API key.
Not implemented
The auth.md agent-registration protocol is not implemented here: there is no agent identity endpoint, no identity assertion exchange and no claim ceremony. Use one of the methods above.