# Agent Identity > Identity, credentials, a spend-limited wallet and an audit trail for AI agents, run by the person who operates them. If you're an AI agent, connect to this site's MCP server at `/api/agent/mcp` (for example `https://www.agntid.lol/api/agent/mcp`) with your own agent key, or call the plain HTTP API with the same key. You don't need a browser: the web pages on this site are your operator's dashboard, not something you sign in to. Paths below are relative to the site you got this file from (for example `https://www.agntid.lol/api/agent/me`). Make the requests with whatever you use for HTTP: curl, fetch, a web-fetch or HTTP tool. Every response is JSON. ## Connect The whole connection is two values: the MCP server URL and your agent key. - **URL:** `/api/agent/mcp` on this site, path included: for example `https://www.agntid.lol/api/agent/mcp`. Use exactly the URL your operator gives you, with `www.`, no trailing slash, query string or fragment. The bare domain (`https://www.agntid.lol`) is the dashboard, which answers with web pages, not MCP, and `https://agntid.lol` redirects to `www`, which drops your key on the way in most clients. - **Key:** one per agent, starting with `agnt_`, sent as the single header `Authorization: Bearer agnt_...`. No client ID, no second secret, no query parameters. Send it to this site only. 1. **Get your agent key.** Only your operator can create one, in the dashboard, which shows it to them once. "Mint new key" on your agent gives them a ready-to-paste MCP config block (the `mcpServers` shape most MCP clients take: the URL plus the header) and the key on its own line, for your secure credential prompt. "New agent" and "Connect to ..." give them a message asking you to connect, with the key kept out of it: they paste the key into your secure credential prompt instead. If you don't have a key, ask your operator for one. Don't try to sign in to the website yourself. 2. **Connect** to the URL as a streamable HTTP MCP server with that header. Each connection starts with its own `initialize`; there's no session to keep. To check a key without connecting (a connector's "test connection"), `GET` the same URL with the header: a good key gets a `200` naming its agent, and a bad one gets the `401` described below. 3. **Call `get_identity` first.** It returns who you are, everything you've been granted, and an `instructions` field written for you that explains how to use each of them. Call it again whenever you need current state instead of relying on an old response. Over plain HTTP instead, send the same header with every request and **start with `GET /api/agent/me`**, which returns the same thing. `POST /api/agent/mcp` is this whole API as one MCP server; the HTTP endpoints are below. **No key? Sign in with AgentID.** If your operator linked your AgentMail inbox to you, `POST /api/agentid/sign-in` with `{ "inbox": "you@agentmail.to" }` and no `Authorization` header. It returns `{ authorizeUrl, pollToken, pollUrl, expiresAt }`. Open `authorizeUrl` and approve the sign-in for your inbox (AgentMail's `authorize_inbox` tool or CLI, or your inbox key's `POST /v0/inboxes/{inbox}/authorize` at AgentMail). Then `POST /api/agentid/sign-in/poll` with `{ "pollToken": "..." }` every couple of seconds: `202` means not yet, and `200` gives `{ sessionToken, expiresAt }`. The session token (`agses_...`) goes in the same `Authorization` header as a key, for 12 hours. A `401` says why in its JSON body's `error`, from the MCP server and the HTTP endpoints alike: `key_missing`, `key_malformed` (not an `agnt_` key: cut short, or saved with quotes or extra text), `key_unknown`, `key_revoked`, `agent_suspended`, `agent_revoked`, `token_invalid` (an OAuth token to refresh), or `session_invalid` (an AgentID session that expired or was signed out: sign in with AgentID again). Apart from `token_invalid` and `session_invalid`, retrying won't help: stop and tell your operator. A `503` with `Retry-After` means the key couldn't be checked just then; try again. Rate limits come back in headers (`Retry-After`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`). **Connecting over OAuth (optional).** A key and the URL is the default way in. If your operator would rather approve you with one tap than copy a key, an MCP client that supports OAuth (MCP's authorization spec) can add the same URL with no key and do the rest itself, so there's nothing to set up by hand. Don't build a connector against the bare domain and run these steps yourself: the tokens only work at `/api/agent/mcp`, so the plain HTTP API (`/api/agent/me` and the rest) answers them with a `401` saying `token_wrong_endpoint`. 1. A request with no `Authorization` header gets a `401` whose `WWW-Authenticate` header points at `/.well-known/oauth-protected-resource/api/agent/mcp`, which leads to `/.well-known/oauth-authorization-server`. 2. The client registers at `/oauth/register`. 3. It sends your operator to `/oauth/authorize`, where they approve you, choosing which of their agents you act as and what you may do. Ask for all three scopes, `vault:read vault:reveal mcp:call`, or leave `scope` out, which asks for all three. The page never grants more than you asked for, and your operator can untick any of them. The three are `vault:read` to look things up, `vault:reveal` to reveal secrets and card numbers, and `mcp:call` for their MCP servers. With `vault:read` alone you can look things up but not use any of them. ## API The main calls. What you can reach depends on what your operator granted you: `GET /api/agent/me` lists it, and its `instructions` explain every call you can make. - `GET /api/agent/me`: who you are and everything you've been granted, plus instructions. Each credential in `connections` has an `account`: `{ name, kind, accountType, signInUrl, ready }`. `signInUrl` is where to use it, `accountType` is `new` (an account of your own), `child` (a login under your operator's account) or `existing` (an account your operator already had), and `ready` is false while an account your operator ordered for you hasn't been created yet: don't use it until it's true, unless `signup` is set, in which case creating it is yours to do. - `POST /api/agent/connections/{service}/reveal`: a credential (password, API key, token) stored for a service - `POST /api/agent/connections`: save the login or API key for an account you just signed up for, granted to you, so you can reveal it later - `POST /api/agent/connections/{service}/rotate`, then `POST /api/agent/connections/{service}/rotate/confirm`: change the password of an account you saved, without losing the one that works - `POST /api/agent/signups/{id}/browser`, then `POST /api/agent/signups/{id}/confirm`: for an account `GET /api/agent/me` says you're to create yourself (`connections[].account.signup`): open its signup browser, sign up with the login you reveal for that service, then confirm. Your operator can watch the browser and take over. - `GET /api/agent/contacts`, then `POST /api/agent/contacts/{id}/reveal`: your operator's address book - `GET /api/agent/delivery-addresses`, then `POST /api/agent/delivery-addresses/{id}/reveal`: places to ship things - `POST /api/agent/wallet/card`, then `POST /api/agent/wallet/card/reveal`: a spend-limited card for a purchase, checked against your policies - `POST /api/agent/mcp/{server}`: an MCP server your operator connected, called with JSON-RPC - `POST /api/agent/link/reveal`: your operator's Stripe Link - `POST /api/agent/external-cards/{id}/reveal`: a payment card your operator added for you Every reveal is logged, whether it's allowed or denied. Reveal a secret right before you use it, not ahead of time. ## Errors Every error is JSON with two fields: a stable `error` code to act on, and an `error_description` sentence saying what happened and what to do next, for example `{ "error": "card_not_found", "error_description": "You have no card with that cardId. ..." }`. Over MCP, a failed tool call has `isError` set and carries the same body as its text. - `401`: your key or token, with the codes under Connect above. - `400` `invalid_body`: the description names each field that's wrong and how; `issues` has the same detail field by field. Fix the request before sending it again. - `400` `secret_required`: an API key or token can't be generated here. Create the new one with its service and send it as `secret`. - `403` `rotation_not_allowed`: you can only rotate a credential you saved yourself. Ask your operator about the others. - `404` `credential_not_found`, `card_not_found` or `browser_not_found`: you have nothing by that name or id. `GET /api/agent/me` lists what you have (`GET /api/agent/browsers` for open browsers). - `404` `browsers_not_granted` or `link_not_granted`: your operator hasn't granted you that. Ask them if you need it; retrying won't help. - `409` `ambiguous_grant`: you were granted more than one of something, and there's no telling which to use. `409` `card_not_active`: that card is frozen or canceled. Either way, tell your operator. - `409` `credential_exists`: you already hold a credential for that service. Reveal it, or save the new one under another service name. - `404` `signup_not_found`: you have no signup by that id. `GET /api/agent/me` lists the accounts you're to create. `409` `signup_not_pending`: it's already done or canceled. - `409` `no_rotation_in_progress`: there's nothing to confirm or cancel. Start a rotation first. - `429` `too_many_browsers`: close one of your browsers first. - `429` `too_many_credentials`: you've saved as many credentials as an agent can. Ask your operator to revoke ones you no longer need. - `502` `upstream_error`: a service this site calls for you (Stripe, Kernel or Mercury) failed, and its own message is in the description. Try again in a little while; if it keeps failing, tell your operator. - `500` `internal_error`: something broke on this site's side. Try again in a moment.