AgentID Sign-In
AgentID Sign-In
An inbox-scoped public key lets a persistent browser create and retain its own
non-extractable P-256 credential for one inbox and sign in as that inbox at
AgentID relying parties. It is an API key of type browser: it has no secret,
and the bearer API key that created it bounds what it may do. That bearer key
is sent only to the AgentMail API. The browser creates the private key and
never exports it.
There are two ways to create one. If the browser is already on an AgentID
sign-in page, authorize that page’s transaction for the inbox with
Authorize Inbox and auth_token,
as this guide shows. If the agent is choosing the browser itself, call
Connect Provider and open the
returned magic_url in it. Both paths produce the same
public key.
Browser sign-in is available to every organization using US production at
https://api.agentmail.to. It is not available in EU production at
https://api.agentmail.eu; these routes return 404 there.
An agent that submits a auth_token read from any origin other than
https://auth.agentid.com can be induced to enroll an attacker’s browser for
its own inbox. Verify the final page origin through the browser or automation
transport itself. The origin fields inside the action are self-asserted and
are not sufficient on their own.
AgentMail API keys are sent only to https://api.agentmail.to; AgentID never requests them.
The AgentID configuration document publishes the same fixed origins and endpoints for discovery. It is not an origin override: do not accept a different origin from runtime input.
Attach flow
- Open an AgentID authorization transaction in a persistent browser.
- When the page reports that enrollment is required, capture its machine action and the browser’s independently reported final URL from the same page observation. Do not combine an action from one page or frame with the URL from another.
- Verify that the final URL’s origin is exactly
https://auth.agentid.com. Also verify the action’s fixed fields and expiry. - Select the inbox from trusted AgentMail configuration; never use
login_hintas the source of authority. If the action publishes a stringlogin_hint, require the selected inbox to match it. Anullaction hint does not prove that the original authorization transaction omitted its hint; the API still checks the original value and may return400. - Send
{auth_token}with the bearer API key to exactlyhttps://api.agentmail.to/v0/inboxes/{inbox_id}/authorize, the fixed endpoint the action publishes, with the selected inbox in the path. The response is the pending public key, read back atGET /v0/api-keys/{api_key_id}. Addaccept_disclosure: trueto accept the relying party’s disclosure on the agent’s behalf. The token is the idempotency anchor, so noIdempotency-Keyis needed. - Keep the existing AgentID page open. It observes the pending key, creates a non-extractable key, proves possession, and continues the same transaction.
Create API Key requires api_key_create.
A new key returns 202; an idempotent retry for the same pending
transaction, inbox, and bearer key returns 200 with the same key:
The response contains no magic_url, AgentID URL,
token, cookie, or navigation instruction. Do not navigate away from the
browser transaction in response to it. Poll
Get API Key with the api_key_id to see
status become active.
A pending key lasts at most five minutes and may expire sooner
with its authorization transaction. An active one lasts at most 30 days.
Remembered consent
lasts 180 days. Treat every returned expires_at as authoritative and connect
again before the current key expires.
Creation is limited to 20 pending keys per bearer API key per
hour, 100 per organization per hour, and five live unactivated keys per
bearer API key. A limit returns 429; honor
its Retry-After header instead of retrying before the indicated time. Delete
an unused pending key or let it expire to release a slot.
Browser activation is separately limited to 20 activations per authorizing
bearer API key per UTC day. Hitting that limit can return 429 from the browser
activation step after the connect call succeeded. Honor Retry-After and wait
for the daily window to reset; deleting a pending key does not reset the
activation counter.
Attach with HTTP
The browser page exposes a machine action with the following shape. Read it only after obtaining the final page URL from the browser transport:
login_hint is always present in the action but may be null. When it is a
string, it is still non-authoritative and must match the trusted inbox selected
by the caller. A null value means only that AgentID did not publish a
safe-shaped hint; the server may still enforce a hint stored on the original
authorization transaction.
These examples use ordinary authenticated HTTP. They validate the fixed endpoint from the action, then send an inbox selected from trusted AgentMail configuration. They never follow an arbitrary URL supplied at runtime.
Manage credentials
Management requests use a bearer API key at https://api.agentmail.to. List
operations require api_key_read; deletion and cancellation require
api_key_delete.
The older /v0/api-keys/browser-credentials list, delete, and events
endpoints, the browser-credentials/enrollments create and cancel endpoints,
the /v0/api-keys/browser-consents list and delete endpoints,
POST /v0/inboxes/{inbox_id}/api-keys with auth_token, and the
/v0/api-keys/public-keys routes have been removed and answer 404; use the
endpoints above.
The list endpoint accepts limit from 1 through 100 and a sealed
page_token. It returns count, the effective limit, an optional
next_page_token, and the api_keys array.
For rotation, connect and verify a new key, then delete the old one. There is no endpoint that extends a key in place.
A key a browser holds is independent of the bearer API key that created it.
It carries exactly two permissions, provider_connect and
provider_share_owner, snapshotted from that bearer key at creation and
enforced from the key itself; change them with
PATCH /v0/api-keys/{api_key_id}. Deleting or narrowing the bearer key
afterward does not affect it.
provider_share_owner is one grouped grant covering both owner scopes. It is
snapshotted as true only when the creating bearer key holds
provider_share_owner, or both of the older owner_profile and owner_email
grants; a bearer key holding just one of those mints keys with
provider_share_owner: false, and can no longer pre-approve that single
scope.
The browser’s Forget action deletes only local key material. It does not
revoke the server-side key. Use DELETE /v0/api-keys/{api_key_id} for
server-side revocation.
Consent behavior
AgentID shows an explicit Allow/Deny review on first use, after a material
change to the requested scopes, callback, or trust configuration, when
remembered consent expires, and when the client sends prompt=consent. An exact
unexpired consent can be reused. With prompt=none, a transaction that cannot
reuse consent returns consent_required to the client instead of opening an
interactive approval.
Remembered consent is not exposed through the API; it expires on its own and is re-reviewed after any material change to the relying party.
Persistent browser support
Use a standard persistent Chromium profile. It supports enrollment, signing after a full browser restart, and re-enrollment after site data is cleared.
Do not promise persistence for private or incognito sessions. Safari and Safari Technology Preview remain unqualified until real-browser enrollment, full restart, signing, and site-data-clear recovery are recorded. A successful short test does not override WebKit’s documented seven-day eviction behavior for script-writable storage. Playwright WebKit is not a shipping Safari qualification. Embedded WebViews must be qualified in the real host application with its configured persistent data store and a full host restart; nonpersistent data stores are unsupported.
Migration from public-key authentication
Inbox-scoped public keys are the current path for persistent browser approval. The AgentID public-key flow remains supported during migration, and no deprecation date is being announced with this release.
