---
name: ident-sh
version: 1.0.0
description: Disposable email addresses for AI agents. Register, generate @ident.sh addresses on demand, and poll for incoming mail via a simple REST API.
homepage: https://ident.sh
metadata: { "category": "email", "api_base": "https://ident.sh" }
---

# ident.sh -- Email for AI Agents

Receive email at `@ident.sh` addresses. Register once, generate addresses on demand, poll for incoming mail.

## Base URL

```
https://ident.sh
```

## Quick Start

```bash
# 1. Register to get a token
POST /api/register
{"nickname": "my-agent"}
# => {"agent_id": "...", "token": "...", "nickname": "my-agent"}

# 2. Generate an email address
POST /api/generate
Authorization: Bearer <token>
# => {"address_id": "...", "address": "a7x9k2m4@ident.sh", "label": null}

# 3. List your addresses
GET /api/addresses
Authorization: Bearer <token>
# => {"addresses": [{"id": "...", "address": "a7x9k2m4@ident.sh", "label": null, "created_at": "..."}]}

# 4. Poll for incoming emails
GET /api/poll
Authorization: Bearer <token>
# => {"emails": [...], "count": N}
```

## Authentication

All endpoints except `/api/register` require a Bearer token in the `Authorization` header:

```
Authorization: Bearer <token>
```

**Important:** The token is returned exactly once at registration and is unrecoverable -- there is no way to retrieve or reset it. You must store it immediately and securely. If lost, you must register a new agent.

## Endpoints

### POST /api/register

Create a new agent and get an auth token. No authentication required.

**Request body:**

```json
{ "nickname": "my-agent" }
```

- `nickname` (required): 1-64 characters, `[a-zA-Z0-9_-]`

**Response (201):**

```json
{
  "agent_id": "uuid",
  "token": "uuid",
  "nickname": "my-agent"
}
```

**Errors:**

- `400` -- Missing or invalid nickname (empty, too long, or invalid characters)
- `400` -- Invalid JSON body

**You must save the `token` immediately -- it is unrecoverable after this response.**

### POST /api/generate

Generate a new email address. Body is optional. Requires authentication.

**Request body (optional):**

```json
{ "label": "signups" }
```

- `label` (optional): a human-readable label for the address

**Response (201):**

```json
{
  "address_id": "uuid",
  "address": "a7x9k2m4@ident.sh",
  "label": "signups"
}
```

**Errors:**

- `400` -- Invalid JSON body
- `401` -- Missing or invalid token
- `500` -- Failed to generate unique address (retry)

### GET /api/addresses

List all email addresses for the authenticated agent, newest first. Requires authentication.

**Query parameters:** None.

**Response (200):**

```json
{
  "addresses": [
    {
      "id": "uuid",
      "address": "a7x9k2m4@ident.sh",
      "label": "signups",
      "created_at": "2025-01-01T00:00:00Z"
    }
  ]
}
```

**Errors:**

- `401` -- Missing or invalid token

### PUT /api/webhook

Set or clear a webhook URL for real-time email notifications. When set, ident.sh will POST the email payload to your URL immediately on receipt. Requires authentication.

**Request body:**

```json
{ "url": "https://example.com/webhook" }
```

- `url` (required): an `https://` URL to receive webhooks, or `null` to clear

**Response (200):**

```json
{ "webhook_url": "https://example.com/webhook" }
```

**Clear webhook:**

```json
{ "url": null }
```

```json
{ "webhook_url": null }
```

**Webhook payload (POST to your URL):**

```json
{
  "id": "uuid",
  "from": "sender@example.com",
  "to": "a7x9k2m4@ident.sh",
  "subject": "Hello",
  "text_body": "Plain text content",
  "html_body": "<p>HTML content</p>",
  "received_at": "2025-01-01T00:00:00Z"
}
```

Webhook delivery is fire-and-forget -- failures are logged but do not affect email storage. You can still use `GET /api/poll` alongside webhooks.

**Errors:**

- `400` -- Invalid JSON, missing url, invalid URL, or non-https URL
- `401` -- Missing or invalid token

### GET /api/poll

Retrieve received emails. Only emails from the last 14 days are returned. Requires authentication.

**Query parameters:**

- `address` (optional): filter by specific address (e.g. `a7x9k2m4@ident.sh`)
- `limit` (optional): max emails to return, 1-100, default 50

**Response (200):**

```json
{
  "emails": [
    {
      "id": "uuid",
      "from": "sender@example.com",
      "to": "a7x9k2m4@ident.sh",
      "subject": "Hello",
      "text_body": "Plain text content",
      "html_body": "<p>HTML content</p>",
      "received_at": "2025-01-01T00:00:00Z"
    }
  ],
  "count": 1
}
```

**Errors:**

- `400` -- No addresses generated yet (call POST /api/generate first)
- `401` -- Missing or invalid token

### DELETE /api/emails

Delete a specific email by ID. Only emails owned by the authenticated agent can be deleted. Requires authentication.

**Query parameters:**

- `id` (required): the email ID to delete

**Response (200):**

```json
{ "deleted": true }
```

**Errors:**

- `400` -- Missing required query parameter: id
- `401` -- Missing or invalid token
- `404` -- Email not found (or not owned by this agent)

## Workflow Example

A typical agent workflow using ident.sh end-to-end:

```bash
# Step 1: Register your agent (one-time)
TOKEN=$(curl -s -X POST https://ident.sh/api/register \
  -H 'Content-Type: application/json' \
  -d '{"nickname": "signup-bot"}' | jq -r '.token')

# Step 2: Generate a fresh address for a sign-up
ADDRESS=$(curl -s -X POST https://ident.sh/api/generate \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"label": "acme-signup"}' | jq -r '.address')

echo "Use $ADDRESS to sign up on the target site"

# Step 3: Sign up on external service using $ADDRESS
# ... (agent performs sign-up) ...

# Step 4: Poll until the confirmation email arrives
while true; do
  EMAILS=$(curl -s "https://ident.sh/api/poll?address=$ADDRESS&limit=1" \
    -H "Authorization: Bearer $TOKEN")
  COUNT=$(echo "$EMAILS" | jq '.count')
  if [ "$COUNT" -gt 0 ]; then
    echo "$EMAILS" | jq '.emails[0]'
    break
  fi
  sleep 5
done

# Step 5: List all your addresses
curl -s https://ident.sh/api/addresses \
  -H "Authorization: Bearer $TOKEN" | jq
```

## Error Format

All errors return JSON:

```json
{ "error": "Description of the problem" }
```

Common HTTP status codes:

- `400` -- Bad request (invalid input)
- `401` -- Unauthorized (missing or invalid token)
- `500` -- Internal server error

## Limits

- Nickname: 1-64 characters
- Poll limit: max 100 emails per request
- Email body: text and HTML truncated to 64KB each
- Email retention: 14 days -- emails older than 14 days are no longer returned by the API
