auth.md

MachineMail Overview

MachineMail gives every AI agent its own email address, ensuring that the inbox is secure and cannot be hijacked. The service supports agentic registration with these steps:

  1. Discover
  2. Register
  3. (Claim if needed)
  4. Exchange for an access_token
  5. Call the API
  6. Handle revocation

Resource Information

Step 1 — Discover

A 401 Unauthorized response from the API and MCP servers indicates a need for metadata:

API Unauthorized:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://machinemail.dev/.well-known/oauth-protected-resource"

MCP Unauthorized:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.machinemail.dev/.well-known/oauth-protected-resource/mcp"

Protected Resource Metadata

GET https://machinemail.dev/.well-known/oauth-protected-resource
{
  "resource": "https://machinemail.dev/",
  "resource_name": "MachineMail",
  "resource_logo_uri": "https://machinemail.dev/favicon.svg",
  "authorization_servers": [ "https://machinemail.dev" ],
  "scopes_supported": [ "inboxes.read", "inboxes.write", "messages.read", "messages.send", "messages.write", "webhooks.read","webhooks.write", "domains.read", "domains.write", "lists.read", "lists.write", "metrics.read", "pods.read", "pods.write", "api_keys.read", "api_keys.write" ],
  "bearer_methods_supported": [ "header" ],
  "resource_documentation": "https://machinemail.dev/auth.md"
}

Authorization Server Metadata

GET https://machinemail.dev/.well-known/oauth-authorization-server
{
  "resource": "https://machinemail.dev/",
  "authorization_servers": [ "https://machinemail.dev" ],
  "scopes_supported": [ "inboxes.read", "inboxes.write", "messages.read", "messages.send", "messages.write", "webhooks.read","webhooks.write", "domains.read", "domains.write", "lists.read", "lists.write", "metrics.read", "pods.read", "pods.write", "api_keys.read", "api_keys.write" ],
  "bearer_methods_supported": [ "header" ],
  "issuer": "https://machinemail.dev",
  "authorization_endpoint": "https://machinemail.dev/oauth2/authorize",
  "token_endpoint": "https://machinemail.dev/oauth2/token",
  "registration_endpoint": "https://machinemail.dev/oauth2/register",
  "revocation_endpoint": "https://machinemail.dev/oauth2/revoke",
  "device_authorization_endpoint": "https://machinemail.dev/auth/cli/device/code",
  "jwks_uri": "https://machinemail.dev/.well-known/jwks.json",
  "service_documentation": "https://machinemail.dev/docs/agents/mcp",
  "grant_types_supported": [ "authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:device_code", "urn:ietf:params:oauth:grant-type:jwt-bearer", "urn:workos:agent-auth:grant-type:claim" ],
  "response_types_supported": [ "code" ],
  "response_modes_supported": [ "query" ],
  "code_challenge_methods_supported": [ "S256" ],
  "token_endpoint_auth_methods_supported": [ "none", "client_secret_post", "client_secret_basic" ],
  "revocation_endpoint_auth_methods_supported": [ "none", "client_secret_post", "client_secret_basic" ],
  "client_id_metadata_document_supported": true,
  "authorization_response_iss_parameter_supported": true,
  "agent_auth": {
    "skill": "https://machinemail.dev/auth.md",
    "identity_endpoint": "https://machinemail.dev/agent/identity",
    "claim_endpoint": "https://machinemail.dev/agent/identity/claim",
    "events_endpoint": "https://machinemail.dev/agent/event/notify",
    "identity_types_supported": ["anonymous", "service_auth"],
    "identity_assertion": { "assertion_types_supported": [] },
    "events_supported": []
  }
}

Step 2 — Pick a Method

Choose one of the following:

  1. Mint an ID-JAG for the audience (aud = https://machinemail.dev) from a trusted provider. (identity_assertion not available yet).
  2. Use user email for service_auth. A claim ceremony is required; nothing works until the user confirms.
  3. Select anonymous for immediate access (sandbox inbox on machinemail.dev) which will expire unless claimed later.

Step 3 — Register

Anonymous Registration

POST https://machinemail.dev/agent/identity
Content-Type: application/json

{ "type": "anonymous", "name": "optional label" }
{
  "registration_id": "reg_...",
  "agent_id": "reg_...",
  "registration_type": "anonymous",
  "identity_assertion": "<service-signed JWT>",
  "assertion_expires": "2026-05-04T13:00:00.000Z",
  "pre_claim_scopes": [ "inboxes.read", "messages.read", "messages.send", "messages.write" ],
  "claim_url": "https://machinemail.dev/agent/identity/claim",
  "claim_token": "clm_...",
  "claim_token_expires": "2026-05-04T13:00:00.000Z",
  "post_claim_scopes": [ "inboxes.read", "inboxes.write", "messages.read", "messages.send", "messages.write", "webhooks.read", "webhooks.write", "domains.read", "domains.write", "lists.read", "lists.write", "metrics.read", "pods.read", "pods.write", "api_keys.read", "api_keys.write" ],
  "inbox": {
    "inbox_id": "agent-xxxx@machinemail.dev",
    "email": "agent-xxxx@machinemail.dev",
    "ephemeral": true,
    "expires_at": "..."
  }
}

Service Authentication

POST https://machinemail.dev/agent/identity
Content-Type: application/json

{ "type": "service_auth", "login_hint": "user@example.com" } 
{
  "registration_id": "reg_...",
  "agent_id": "reg_...",
  "registration_type": "service_auth",
  "claim_url": "https://machinemail.dev/agent/identity/claim",
  "claim_token": "clm_...",
  "claim_token_expires": "...",
  "post_claim_scopes": [ "inboxes.read", "inboxes.write", "messages.read", "messages.send", "messages.write", "webhooks.read", "webhooks.write", "domains.read", "domains.write", "lists.read", "lists.write", "metrics.read", "pods.read", "pods.write", "api_keys.read", "api_keys.write" ],
  "claim": {
    "user_code": "123456",
    "expires_in": 600,
    "verification_uri": "https://machinemail.dev/claim?claim_attempt_token=cat_...",
    "interval": 5
  }
}

Step 4 — Claim Ceremony

To claim an anonymous registration:

POST https://machinemail.dev/agent/identity/claim
Content-Type: application/json

{ "claim_token": "clm_...", "email": "user@example.com" }

Completing the Claim

The email parameter is optional but recommended. Use the user's real email for claiming the agent.

Poll for Completion

For successful claim completion, make a token request:

POST https://machinemail.dev/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_...
{
  "access_token": "<post-claim access_token>",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "inboxes.read inboxes.write messages.read messages.send messages.write webhooks.read webhooks.write domains.read domains.write lists.read lists.write metrics.read pods.read pods.write api_keys.read api_keys.write",
  "identity_assertion": "<service-signed JWT>",
  "assertion_expires": "..."
}

Step 5 — Use Access Token

GET https://machinemail.dev/v0/inboxes
Authorization: Bearer <access_token>

Scopes

Scope Grants Pre-claim
inboxes.read List and read inboxes. yes (sandbox only)
inboxes.write Create, update, and delete inboxes. no
messages.read Read messages, threads, attachments, and trust reports. yes (sandbox only)
messages.send Send, reply to, and forward messages. yes (sandbox only)
messages.write Change labels on and delete messages. yes (sandbox only)
webhooks.read List webhooks and deliveries. no
webhooks.write Create, update, and delete webhooks. no
domains.read List domains and their DNS records. no
domains.write Manage custom domains. no
lists.read Read allow/block lists. no
lists.write Manage allow/block lists. no
metrics.read Read metrics and event logs. no
pods.read List pods. no
pods.write Manage pods. no
api_keys.read List API keys. no
api_keys.write Manage API keys. no

Errors

Code Where Action
anonymous_not_enabled /agent/identity Pick another method.
invalid_request /agent/identity, /agent/identity/claim, /oauth2/token Fix the request body.
interaction_required (401) /agent/identity Surface the claim block to the user.
claimed_or_in_flight (409) /agent/identity/claim Poll for token.
registration_blocked (403) /agent/identity Registration not available from network.

Revocation