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
4 changes: 2 additions & 2 deletions bin/agentmail-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { fileURLToPath } from "url";

const fernDir = join(dirname(fileURLToPath(import.meta.url)), "..", "fern");
const instances = [
"https://agentmail-production.docs.buildwithfern.com",
"https://agentmail-production.docs.buildwithfern.com/docs",
"agentmail-production.docs.buildwithfern.com",
"agentmail-production.docs.buildwithfern.com/docs",
] as const;

function fern(args: string[]) {
Expand Down
22 changes: 9 additions & 13 deletions fern/changelog/2026-09-05-agentid-sign-in-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,20 @@ Build agents that:
- Wait on a pending sign-in by polling one endpoint instead of diffing a list
- Audit and revoke every credential that can act as an inbox, bearer and sign-in keys alike, from one list

Python SDK 0.5.10 does not include these routes; the Python example uses `httpx`. The TypeScript example uses SDK 0.5.25.
The examples below use the current SDK methods, available in Python 0.6.0 and TypeScript 0.5.26.

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

response = httpx.post(
"https://api.agentmail.to/v0/providers/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/connect",
headers={"Authorization": f"Bearer {os.environ['AGENTMAIL_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4())},
json={"inbox_id": "agent@example.com"},
timeout=30,
from agentmail import AgentMail, ConnectProviderBody

client = AgentMail()
connection = client.providers.connect(
provider_id=uuid.UUID("d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32"),
request=ConnectProviderBody(inbox_id="agent@example.com"),
request_options={"additional_headers": {"Idempotency-Key": str(uuid.uuid4())}},
)
response.raise_for_status()
connection = response.json()
print(connection["magic_url"], connection["api_key_id"])
print(connection.magic_url, connection.api_key_id)
```

```typescript title="TypeScript"
Expand Down
73 changes: 73 additions & 0 deletions fern/changelog/2026-09-16-sdk-cli-updates.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
tags: ["domains-api", "providers-api", "breaking-change", "sdk"]
---

## Summary

Register domains that already use Google Workspace and inspect a provider's sign-up limit with the updated SDKs and CLI. Python also gains the current AgentID sign-in and API-key management methods, inbox search, and pagination for messages in a thread.

### What's new?

- Domain creation accepts `allow_conflicting_provider` on `POST /v0/domains` and `POST /v0/pods/{pod_id}/domains`. Set it to `true` to allow registration alongside Google Workspace; DNS and inbound routing still need to be configured separately. Conflicting registrations without the flag return `422`.
- Provider responses include optional `owner_signup_limit`. It limits accounts your organization can sign up at that provider; `0` pauses new sign-ups, while existing accounts can continue signing in. Omission means no configured limit.
- Python includes providers and accounts resources, `inboxes.authorize` with `auth_token` and `accept_disclosure`, the current API Keys methods, organization and pod inbox search, and thread-message pagination with `limit` and `page_token`.
- CLI 1.5.0 adds `--allow-conflicting-provider true` to `agentmail domains create` and `agentmail pods domains create`, and includes the provider limit in its schema.

### Breaking changes

⚠️ Python 0.6.0 removes the previous dedicated public-key management, enrollment, consent, and bulk-revocation methods. Use the API Keys methods and authorize pending sign-ins through `inboxes.authorize`.

Before, public keys used a dedicated list method:

```python
client.api_keys.list_public_keys()
```

Now, filter the API Keys list:

```python
client.api_keys.list(type="public_key")
```

Key creation and list responses can contain bearer or public-key credentials. Check `type` before accessing fields specific to one family. Scope is selected by the organization, pod, or inbox route; public-key responses identify it with `pod_id` and `inbox_id` instead of a `scope` object.

Thread responses include a page of messages. Follow `next_page_token` until it is absent to retrieve the complete thread.

### Use cases

Build agents that:

- Register a shared Google Workspace domain before configuring its routing
- Check a provider's account limit before starting a new sign-up
- Manage sign-in keys and retrieve complete message threads using the Python SDK

### SDK Updates

- [Python SDK 0.6.0](https://github.com/agentmail-to/agentmail-python/releases/tag/0.6.0)
- [TypeScript SDK 0.5.26](https://github.com/agentmail-to/agentmail-node/releases/tag/0.5.26)
- [CLI 1.5.0](https://github.com/agentmail-to/agentmail-cli/releases/tag/v1.5.0)

<CodeBlocks>
```python title="Python"
from agentmail import AgentMail

client = AgentMail()
keys = client.api_keys.list(type="public_key")
for key in keys.api_keys:
print(key.api_key_id, key.inbox_id)
```

```typescript title="TypeScript"
import { AgentMailClient } from "agentmail";

const client = new AgentMailClient();
const keys = await client.apiKeys.list({ type: "public_key" });
for (const key of keys.apiKeys) {
console.log(key.apiKeyId, key.inboxId);
}
```
</CodeBlocks>

<Note>
Follow the [AgentID Sign-In guide](https://docs.agentmail.to/agentid-sign-in) for current SDK examples and credential management.
</Note>
28 changes: 13 additions & 15 deletions fern/pages/guides/agentid-public-key-authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Use a bearer API key with `api_key_create` to register keys. Reading, updating,
Install the TypeScript SDK with `npm install agentmail@latest`, or the CLI with `npm install -g agentmail-cli@latest`. Set `AGENTMAIL_API_KEY` in your environment.

<Note>
The examples use TypeScript SDK 0.5.25 and CLI 1.4.0. Python SDK 0.5.10 still exposes the previous public-key endpoints. The Python example uses the current HTTP route with `httpx`; install its dependencies with `pip install httpx cryptography`.
The examples use Python SDK 0.6.0, TypeScript SDK 0.5.26, and CLI 1.5.0. Install the Python dependencies with `pip install --upgrade agentmail cryptography`.
</Note>

<Warning>
Expand All @@ -30,8 +30,7 @@ The following examples generate a P-256 key and register it for one inbox. They
<CodeBlocks>
```python title="Python"
import base64
import os
import httpx
from agentmail import AgentMail, ApiKeyPermissions, CreatePublicKeyRequest, PublicJwk
from cryptography.hazmat.primitives.asymmetric import ec

private_key = ec.generate_private_key(ec.SECP256R1())
Expand All @@ -40,19 +39,18 @@ numbers = private_key.public_key().public_numbers()
def coordinate(value: int) -> str:
return base64.urlsafe_b64encode(value.to_bytes(32, "big")).rstrip(b"=").decode()

public_key = {
"kty": "EC", "crv": "P-256",
"x": coordinate(numbers.x), "y": coordinate(numbers.y),
}
response = httpx.post(
"https://api.agentmail.to/v0/inboxes/agent%40example.com/api-keys",
headers={"Authorization": f"Bearer {os.environ['AGENTMAIL_API_KEY']}"},
json={"public_key": public_key, "client_id": "production-signer-v1",
"name": "production signer", "permissions": {"provider_connect": True}},
timeout=30,
client = AgentMail()
credential = client.inboxes.api_keys.create(
inbox_id="agent@example.com",
request=CreatePublicKeyRequest(
public_key=PublicJwk(kty="EC", crv="P-256",
x=coordinate(numbers.x), y=coordinate(numbers.y)),
client_id="production-signer-v1",
name="production signer",
permissions=ApiKeyPermissions(provider_connect=True),
),
)
response.raise_for_status()
print(response.json()["api_key_id"])
print(credential.api_key_id)
```

```typescript title="TypeScript"
Expand Down
53 changes: 21 additions & 32 deletions fern/pages/guides/agentid-sign-in.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ A sign-in credential has `type: "public_key"` and a `status` of `pending` or `ac
- Enable `api_key_read` to check key status, `api_key_update` to change permissions, and `api_key_delete` to revoke a key.
- Use the US API at `https://api.agentmail.to` for these sign-in flows.

Install the [CLI](https://docs.agentmail.to/integrations/cli) with `npm install -g agentmail-cli@latest`, or the TypeScript SDK with `npm install agentmail@latest`. Set `AGENTMAIL_API_KEY` in your environment.
Install the [CLI](https://docs.agentmail.to/integrations/cli) with `npm install -g agentmail-cli@latest`, the Python SDK with `pip install --upgrade agentmail`, or the TypeScript SDK with `npm install agentmail@latest`. Set `AGENTMAIL_API_KEY` in your environment.

<Note>
These examples were checked against CLI 1.4.0 and TypeScript SDK 0.5.25. Python SDK 0.5.10 does not include the current sign-in endpoints, so the Python examples call the same API with `httpx` (`pip install httpx`).
These examples use Python SDK 0.6.0, TypeScript SDK 0.5.26, and CLI 1.5.0. Upgrade older installations to use the current sign-in and API Keys methods.
</Note>

## Connect to a provider
Expand All @@ -34,20 +34,16 @@ agentmail providers connect \

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

response = httpx.post(
"https://api.agentmail.to/v0/providers/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/connect",
headers={"Authorization": f"Bearer {os.environ['AGENTMAIL_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4())},
json={"inbox_id": "agent@example.com"},
timeout=30,
from agentmail import AgentMail, ConnectProviderBody

client = AgentMail()
connection = client.providers.connect(
provider_id=uuid.UUID("d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32"),
request=ConnectProviderBody(inbox_id="agent@example.com"),
request_options={"additional_headers": {"Idempotency-Key": str(uuid.uuid4())}},
)
response.raise_for_status()
connection = response.json()
print(connection["magic_url"], connection["api_key_id"])
print(connection.magic_url, connection.api_key_id)
```

```typescript title="TypeScript"
Expand Down Expand Up @@ -89,17 +85,14 @@ agentmail inboxes authorize \
<CodeBlocks>
```python title="Python"
import os
import httpx
from agentmail import AgentMail

response = httpx.post(
"https://api.agentmail.to/v0/inboxes/agent%40example.com/authorize",
headers={"Authorization": f"Bearer {os.environ['AGENTMAIL_API_KEY']}"},
json={"auth_token": os.environ["AGENTID_AUTH_TOKEN"]},
timeout=30,
client = AgentMail()
key = client.inboxes.authorize(
inbox_id="agent@example.com",
auth_token=os.environ["AGENTID_AUTH_TOKEN"],
)
response.raise_for_status()
key = response.json()
print(key["api_key_id"], key["status"])
print(key.api_key_id, key.status)
```

```typescript title="TypeScript"
Expand Down Expand Up @@ -131,16 +124,12 @@ agentmail api-keys get --api-key-id 4d795cc3-ae87-4f84-85e3-4ad4ca656f44

<CodeBlocks>
```python title="Python"
import os
import httpx
from agentmail import AgentMail

response = httpx.get(
"https://api.agentmail.to/v0/api-keys/4d795cc3-ae87-4f84-85e3-4ad4ca656f44",
headers={"Authorization": f"Bearer {os.environ['AGENTMAIL_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
print(response.json().get("status"))
client = AgentMail()
key = client.api_keys.get(api_key_id="4d795cc3-ae87-4f84-85e3-4ad4ca656f44")
if key.type == "public_key":
print(key.status)
```

```typescript title="TypeScript"
Expand Down
11 changes: 11 additions & 0 deletions fern/pages/integrations/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ Shell completions (`agentmail completion`) and man pages (`agentmail man`) are b
- **`--dry-run` is not an acceptance guarantee.** Flag values are type-checked locally, so `--limit abc` fails before a request is made. `--dry-run` then shows the request that would be sent — the API can still reject it on grounds the CLI cannot check, such as an unknown ID or a permission error.
- **No auto-pagination.** List commands return one page. Paginate manually: pass `--limit`, read `next_page_token` from the response, and pass it back as `--page-token`.

## Upgrading to 1.5

Version 1.5 adds `--allow-conflicting-provider true` to domain creation, including
`agentmail pods domains create`, so you can register a domain that already uses
Google Workspace. Configure DNS and inbound routing separately using the
[Google Workspace guide](https://docs.agentmail.to/google-workspace).

Provider responses now include optional `owner_signup_limit`: the maximum number
of accounts your organization can sign up at that provider. `0` pauses new
sign-ups; existing accounts can still sign in. Omission means no configured limit.

## Upgrading to 1.4

Public keys and AgentID sign-in keys use the same `api-keys` commands as bearer
Expand Down
35 changes: 32 additions & 3 deletions openapi/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,12 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ValidationErrorResponse'
'422':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
summary: Create Domain
servers:
- url: https://api.agentmail.to
Expand Down Expand Up @@ -4989,6 +4995,12 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ValidationErrorResponse'
'422':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
summary: Create Domain
servers:
- url: https://api.agentmail.to
Expand Down Expand Up @@ -9138,6 +9150,23 @@ components:
properties:
domain:
$ref: '#/components/schemas/DomainName'
allow_conflicting_provider:
type: boolean
nullable: true
description: >-
Allow registration when the domain already has Google Workspace MX
records.

Defaults to false; registration otherwise returns 422 when a
conflicting

provider is detected.

This flag does not configure DNS or inbound routing. For shared
Google

Workspace domains, follow the [Google Workspace
guide](/google-workspace).
feedback_enabled:
$ref: '#/components/schemas/FeedbackEnabled'
nullable: true
Expand Down Expand Up @@ -10953,9 +10982,9 @@ components:
type: integer
nullable: true
description: >-
Maximum number of accounts your organization may sign up at this provider. Omitted when
the provider sets no limit. 0 means the provider has paused new sign-ups; existing accounts
keep signing in.
Maximum number of accounts your organization may sign up at this
provider. Omitted when the provider sets no limit. 0 means the
provider has paused new sign-ups; existing accounts keep signing in.
required:
- provider_id
ListProvidersResponse:
Expand Down
Loading