Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions fern/apis/api/definition/api-keys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ types:
docs: ID of the inbox.

PublicKeyScope:
docs: The immutable scope in which a public-key credential can approve AgentID sign-in.
docs: The immutable scope of a public-key credential.
union:
organization: OrganizationPublicKeyScope
pod: PodPublicKeyScope
Expand All @@ -82,9 +82,9 @@ types:

PublicKeyCredential:
docs: |
An AgentID sign-in credential. `type` and `api_key_id` are server-owned;
use `api_key_id` as the JWS `kid`. This response never contains a bearer
secret or private key.
A registered public-key credential for signed requests. `type` and
`api_key_id` are server-owned; `api_key_id` is the credential's JWS `kid`.
This response never contains a bearer secret or private key.
properties:
api_key_id:
type: uuid
Expand All @@ -108,9 +108,9 @@ types:

CreatePublicKeyRequest:
docs: |
Register only a public P-256 JWK. Credential type, `api_key_id`, sign-in
eligibility, permissions, and generation are server-owned and are not
request properties.
Register only a public P-256 JWK. Credential type, `api_key_id`,
permissions, and generation are server-owned and are not request
properties.
properties:
public_key: PublicJwk
name:
Expand All @@ -132,8 +132,8 @@ types:

UpdatePublicKeyNameRequest:
docs: |
Rename a public-key credential. Key material, ID, type, scope, sign-in
eligibility, permissions, generation, and expiry are immutable.
Rename a public-key credential. Key material, ID, type, scope,
permissions, generation, and expiry are immutable.
properties:
name:
type: string
Expand All @@ -150,7 +150,7 @@ types:
docs: Public-key credentials only, ordered by creation time descending by default.

RevokeAllAgentIdSignInKeysResponse:
docs: Permanent idempotency receipt for an organization-wide AgentID sign-in key revocation.
docs: Permanent idempotency receipt for an organization-wide public-key credential revocation.
properties:
previous_generation:
type: integer
Expand Down
59 changes: 59 additions & 0 deletions fern/changelog/2026-09-05-agentid-approval-retired.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
tags: ["agentid", "api-keys", "breaking-change", "docs"]
---

## Summary

AgentID sign-in now runs entirely through browser enrollment. The agent-signed
approval endpoint is retired, so an agent no longer generates, stores, or signs
with its own P-256 key to complete a sign-in: it enrolls the browser once with
ordinary authenticated HTTP, and every later sign-in completes from that browser.

### Breaking changes

鈿狅笍 **`POST https://auth.agentid.com/authorize/approve` has been removed.** The
AgentID waiting page no longer prints a request id, and the agent-facing
approval guide is gone. Sign-ins that relied on a registered public key signing
the request id must move to
[AgentID browser enrollment](https://docs.agentmail.to/agentid-browser-enrollment).
Production recorded no agent-key approvals in the 90 days before this change.

Public-key credentials themselves are unchanged. `POST /v0/api-keys/public-keys`,
the list, rename, and revoke operations, and
`POST /v0/api-keys/public-keys/agentid-sign-in/revoke-all` keep working as the
lifecycle for registered signing keys; those keys are now signed-request
credentials rather than AgentID sign-in credentials.

**Migration guide:**

<CodeBlocks>
```python title="Python"
import httpx

# enroll the browser waiting on the agentid page; transaction_jti comes from that page's action
response = httpx.post(
"https://api.agentmail.to/v0/inboxes/agent@yourdomain.agentmail.to/browser-credentials/enrollments",
headers={"Authorization": "Bearer am_us_..."},
json={"transaction_jti": "<transaction_jti from the waiting page>"},
timeout=10,
)
response.raise_for_status()
```

```typescript title="TypeScript"
// enroll the browser waiting on the agentid page; transaction_jti comes from that page's action
const response = await fetch(
'https://api.agentmail.to/v0/inboxes/agent%40yourdomain.agentmail.to/browser-credentials/enrollments',
{
method: 'POST',
headers: { Authorization: 'Bearer am_us_...', 'Content-Type': 'application/json' },
body: JSON.stringify({ transaction_jti: '<transaction_jti from the waiting page>' }),
},
)
if (!response.ok) throw new Error(`Enrollment failed: ${response.status}`)
```
</CodeBlocks>

<Note>
Follow the [AgentID browser enrollment guide](https://docs.agentmail.to/agentid-browser-enrollment) for the origin checks an agent must perform before submitting a `transaction_jti`.
</Note>
6 changes: 3 additions & 3 deletions fern/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ redirects:
- source: /integrations/moltbot
destination: /integrations/openclaw
permanent: true
- source: /agentid-public-key-authentication
destination: /agentid-browser-enrollment
permanent: true
- source: /integrations/ai-onboarding
destination: /integrations/agent-onboarding
permanent: true
Expand Down Expand Up @@ -320,9 +323,6 @@ navigation:
- page: AgentID Browser Enrollment
icon: fa-solid fa-shield-halved
path: pages/guides/agentid-browser-enrollment.mdx
- page: AgentID Public-Key Authentication
icon: fa-solid fa-key
path: pages/guides/agentid-public-key-authentication.mdx
- page: Sending & Receiving Email
icon: fa-solid fa-right-left
path: pages/guides/sending-receiving-email.mdx
Expand Down
14 changes: 9 additions & 5 deletions fern/pages/guides/agentid-browser-enrollment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,12 @@ 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

Browser enrollment is the current path for persistent browser approval. The
[AgentID public-key flow](/agentid-public-key-authentication) remains supported
during migration, and no deprecation date is being announced with this release.
## Retired public-key approval

Browser enrollment is the only agent-driven AgentID sign-in. The earlier
public-key approval flow is retired: `POST https://auth.agentid.com/authorize/approve`
no longer exists, and the waiting page no longer prints a request id for an
agent to sign. Public-key credentials registered through
`POST /v0/api-keys/public-keys` remain valid as signed-request keys, but they
no longer sign an agent in to AgentID. An agent that still holds one should
enroll its browser as described above.
Loading
Loading