{
  "openapi": "3.1.0",
  "info": {
    "title": "Dead Simple Email API",
    "version": "0.1.0",
    "description": "Email API for AI agents. Create inboxes, send and receive email,\nmanage threads, and get real-time webhook notifications.\n\n## Authentication\nAll authenticated endpoints use Bearer token auth:\n```\nAuthorization: Bearer dse_your_api_key\n```\n\n## Agent self-signup\nAutonomous agents can provision an account, a key, and a live inbox in one\nunauthenticated call \u2014 no human, no verification email:\n```\nPOST /v1/auth/agent-signup\n```\nThat returns a `trial` account (1 inbox, 10 sends/hour, 25 sends/day) with a\nscoped key. `POST /v1/auth/claim` attaches a verified email and moves it to\nthe Free plan, keeping the same key, inboxes and history.\n\n## Sign in with Dead Simple (OpenID Connect)\n`https://id.deadsimple.email` is an OpenID Connect provider where the\nidentity is an agent's inbox: `sub` is the `inbox_id`, `email` is the inbox\naddress. Discovery at `/.well-known/openid-configuration`, JWKS at\n`/.well-known/jwks.json`, ES256 id_tokens, authorization-code + PKCE S256,\nRFC 7591 registration at `/register`. Open clients (client_id = the app's\nhttps origin) need no registration. An agent authenticates at `/authorize`\nwith `Authorization: Bearer dse_...` plus `inbox_id=`, or with an ES256\nassertion signed by a key enrolled via `/v1/inboxes/{inbox_id}/identity/keys`;\nthe one-call helper `POST /v1/inboxes/{inbox_id}/identity/sign-in` wraps\nthis for SDKs and the MCP server. Endpoints on the `id.deadsimple.email`\nhost are tagged **Identity Provider** below and carry their own `servers`\nentry.\n\n## Pay per request (no API key)\nTwelve priced routes can be called with no credentials at all. They answer\n`402 Payment Required` carrying an x402 v2 `PAYMENT-REQUIRED` header (USDC\non Base, Polygon or Solana, `exact` scheme, PayAI facilitator; the same\nJSON is repeated in the body for v1 clients) and, on `POST /v1/inboxes`,\na `WWW-Authenticate: Payment` challenge for Stripe's Machine Payments\nProtocol. Retry with `PAYMENT-SIGNATURE` (x402 v2), `X-PAYMENT` (v1) or\n`Authorization: Payment <credential>` (MPP). x402 payments are verified\nbefore the work and settled after it; MPP charges first and refunds if\nthe work fails. Prices: inbox $1.00, send/reply/reply-all/forward $0.01,\nreads $0.005. The paying wallet keys a `payg` account, and the first paid\ninbox returns `credentials` (an API key) in the response so later reads\nand sends within the plan are free. See the reusable `402` response and\nhttps://deadsimple.email/pay-per-request.html.\n\n## Idempotency\nPOST endpoints accept an `Idempotency-Key` header. Same key within 24h\nreturns the cached response without re-executing.\n\n## Rate Limits\nEvery response includes rate limit headers:\n- `X-RateLimit-Limit` \u2014 requests per window\n- `X-RateLimit-Remaining` \u2014 remaining requests\n- `X-RateLimit-Reset` \u2014 window reset timestamp\n\nOn `429`, a `Retry-After` header gives the seconds to wait. Per-account\nlimits scale with plan (`rate_limit_rpm`); public/unauthenticated endpoints\nare additionally limited per IP.\n\n## Webhook Reliability\nEvery event is a durable delivery: the first attempt runs immediately and\nfailures are retried on an exponential-backoff schedule (configurable per\nwebhook via `/v1/webhooks/{id}/config`; default `[1, 30, 300, 1800, 7200,\n86400]` seconds). Deliveries are HMAC-SHA256 signed on **all plans**. The\nper-webhook delivery log (`/v1/webhooks/{id}/deliveries`) records every\nattempt with status and error, and any delivery can be replayed. Endpoints\nthat fail repeatedly are auto-disabled.\n\n## WebSocket Streaming\nConnect to `wss://ws.deadsimple.email?api_key=dse_...` for real-time events.\n\nAfter connecting, subscribe to specific inboxes/events:\n```json\n{\"action\": \"subscribe\", \"inbox_ids\": [\"...\"], \"events\": [\"message.received\"]}\n```\n\nEvents are pushed as JSON with the same payload as webhooks. Send `{\"action\": \"ping\"}`\nto keep the connection alive (10-minute idle timeout).\n",
    "contact": {
      "url": "https://deadsimple.email"
    },
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://api.deadsimple.email",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key (dse_...), session token (JWT), or OAuth 2.1 access token (dse_oat_..., obtained via the authorization-code + PKCE flow below)"
      },
      "OAuth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 for MCP clients. Public clients only (PKCE S256 required, no client secret). Supports RFC 7591 dynamic client registration at /oauth/register and discovery via /.well-known/oauth-authorization-server. Access tokens carry inbox/message permissions only (no billing, team, or API-key administration).",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.deadsimple.email/oauth/authorize",
            "tokenUrl": "https://api.deadsimple.email/oauth/token",
            "refreshUrl": "https://api.deadsimple.email/oauth/token",
            "scopes": {
              "email": "Send, receive, and manage email inboxes"
            }
          }
        }
      },
      "OpenIDConnect": {
        "type": "openIdConnect",
        "openIdConnectUrl": "https://id.deadsimple.email/.well-known/openid-configuration",
        "description": "Sign in with Dead Simple. Relying parties use this to authenticate an agent by its inbox; it is not used to call the Dead Simple API itself. Scopes: openid, email, profile (open clients); owner_email, org, offline_access (registered clients only)."
      }
    },
    "parameters": {
      "WorkspaceHeader": {
        "name": "X-Workspace-Id",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "description": "Target a specific workspace. Required for account-wide API keys that want workspace-scoped results."
      }
    },
    "responses": {
      "PaymentRequired": {
        "description": "Payment required. The request had no API key and this route can be paid per call. The x402 requirements are in the PAYMENT-REQUIRED header and repeated in the body; routes priced at or above $0.50 (inbox creation) also carry a Stripe MPP challenge in WWW-Authenticate. A rejected or mismatched payment gets this same response again with error.reason explaining why. Responses are Cache-Control no-store and expose the payment headers to browsers.",
        "headers": {
          "PAYMENT-REQUIRED": {
            "description": "Base64 JSON, x402 v2 PaymentRequired object: x402Version, resource, accepts (one entry per network with scheme, network, amount in atomic USDC, asset, payTo, maxTimeoutSeconds, extra), extensions.",
            "schema": {
              "type": "string"
            }
          },
          "WWW-Authenticate": {
            "description": "Stripe MPP challenge, only when the price is at least $0.50: `Payment id=\"...\", realm=\"api.deadsimple.email\", method=\"stripe\", intent=\"charge\", expires=\"<ISO 8601>\", request=\"<base64url JCS JSON {amount (cents), currency, description, methodDetails}>\"`. Valid five minutes, single use.",
            "schema": {
              "type": "string"
            }
          },
          "Cache-Control": {
            "schema": {
              "type": "string",
              "example": "no-store"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaymentRequiredBody"
            }
          }
        }
      }
    },
    "schemas": {
      "CalendarInvite": {
        "type": "object",
        "description": "A calendar invitation carried in the message body, which is what makes the recipient's mail client show Accept/Decline and puts the event on their calendar. Attaching an .ics file does not do this: it arrives as a download nobody can act on. Times need a zone -- a trailing \"Z\", an offset, or `timezone`. Attendees default to the message's own to + cc. The send response returns `calendar_uid`; keep it, because rescheduling (same uid, higher sequence) and cancelling (method CANCEL) are matched to the original event by UID.\n",
        "properties": {
          "title": {
            "type": "string",
            "description": "Event title, as it appears on the calendar"
          },
          "start": {
            "type": "string",
            "description": "ISO 8601 start. A bare date (\"2026-09-15\") makes it all-day.\n"
          },
          "end": {
            "type": "string",
            "description": "ISO 8601 end. Omit to use duration_minutes."
          },
          "duration_minutes": {
            "type": "integer",
            "default": 30,
            "description": "Length when `end` is absent"
          },
          "timezone": {
            "type": "string",
            "description": "IANA zone for a local time carrying no offset, e.g. \"America/New_York\". Required for a naive start/end, since otherwise the meeting would land at the wrong hour.\n"
          },
          "location": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "attendees": {
            "type": "array",
            "description": "Defaults to the message's to + cc",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "optional": {
                      "type": "boolean"
                    }
                  }
                }
              ]
            }
          },
          "reminder_minutes": {
            "type": "integer",
            "description": "Alarm this many minutes before the event"
          },
          "all_day": {
            "type": "boolean"
          },
          "recurrence": {
            "type": "string",
            "description": "RFC 5545 rule, e.g. \"FREQ=WEEKLY;COUNT=4\""
          },
          "uid": {
            "type": "string",
            "description": "Pass the uid of an event already sent to reschedule or cancel it. Omit for a new invitation.\n"
          },
          "sequence": {
            "type": "integer",
            "default": 0,
            "description": "Revision number. Must rise above the last one sent whenever an existing event changes, or clients ignore the update.\n"
          },
          "method": {
            "type": "string",
            "enum": [
              "REQUEST",
              "CANCEL",
              "PUBLISH"
            ],
            "default": "REQUEST",
            "description": "REQUEST asks for an RSVP. CANCEL withdraws an event (uid required). PUBLISH announces one with no RSVP.\n"
          },
          "ics": {
            "type": "string",
            "description": "Your own iCalendar object, instead of the fields above. The MIME method parameter is read from its METHOD line.\n"
          }
        },
        "example": {
          "title": "Roof inspection - 124 Lakeshore Dr",
          "start": "2026-09-15T15:00:00",
          "timezone": "America/New_York",
          "duration_minutes": 45,
          "location": "124 Lakeshore Dr"
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "validation_error"
              },
              "message": {
                "type": "string",
                "example": "Email is required"
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "Meta": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "is_default": {
            "type": "boolean"
          },
          "inbox_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WorkspaceList": {
        "type": "object",
        "properties": {
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Workspace"
            }
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "Inbox": {
        "type": "object",
        "properties": {
          "inbox_id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "local_part": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "message_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "message_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid"
          },
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "from_email": {
            "type": "string",
            "format": "email"
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "subject": {
            "type": "string"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "User-defined labels for organizing and filtering messages"
          },
          "text_body": {
            "type": "string"
          },
          "html_body": {
            "type": "string"
          },
          "latest_reply": {
            "type": "string"
          },
          "tracking_id": {
            "type": "string",
            "format": "uuid",
            "description": "Present when open/click tracking is enabled for this message"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "received",
              "bounced",
              "scheduled"
            ]
          },
          "internet_message_id": {
            "type": "string",
            "description": "The RFC 5322 Message-ID header of the email (angle brackets included). Identical on every copy of the same email, so it is the key to deduplicate on. Absent if the email arrived without one.\n"
          },
          "is_spam": {
            "type": "boolean",
            "description": "Whether the message was detected as spam (inbound only)"
          },
          "spam_score": {
            "type": "number",
            "format": "float",
            "description": "Spam confidence score (higher = more likely spam)"
          },
          "injection_risk": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "medium",
              "high"
            ],
            "description": "Prompt-injection risk level for this inbound message. Every inbound email is scanned for instructions that try to hijack an agent reading it (e.g. \"ignore previous instructions\", \"run this command\"). Present on inbound messages that were scanned. Use this to gate whether an agent should act on message content autonomously.\n"
          },
          "injection_score": {
            "type": "number",
            "format": "float",
            "description": "Prompt-injection confidence score from 0.0 to 1.0. Pairs with injection_risk. Present when injection_risk is set.\n"
          },
          "extracted": {
            "type": "object",
            "description": "Auto-extracted structured data from inbound verification/auth emails, so agents can complete signup and 2FA flows without parsing bodies. Present on inbound messages (with body) when a code or link is found.\n",
            "properties": {
              "verification_code": {
                "type": "string",
                "description": "The most likely one-time code (OTP), 4\u20138 digits."
              },
              "magic_link_url": {
                "type": "string",
                "description": "The most likely verification / magic-link URL."
              },
              "expires_in": {
                "type": "string",
                "description": "Human-readable expiry if stated in the email (e.g. \"10 minutes\")."
              },
              "all_codes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "All candidate codes found, best-first."
              },
              "all_links": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "All candidate verification links found, best-first."
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TrackingStats": {
        "type": "object",
        "properties": {
          "message_id": {
            "type": "string",
            "format": "uuid"
          },
          "opens": {
            "type": "integer"
          },
          "clicks": {
            "type": "integer"
          },
          "last_opened_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_clicked_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Attachment": {
        "type": "object",
        "properties": {
          "attachment_id": {
            "type": "string",
            "format": "uuid"
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "extracted_text": {
            "type": "string",
            "description": "Readable text extracted from the attachment (PDF, XLSX, DOCX, CSV, TXT, HTML, JSON). Present only for supported types up to 10 MB; truncated at 50k characters. Absent for images/binaries \u2014 use the download URL for those.\n"
          }
        }
      },
      "Thread": {
        "type": "object",
        "properties": {
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "subject": {
            "type": "string"
          },
          "message_count": {
            "type": "integer"
          },
          "participants": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "latest_message": {
            "type": "object"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.sent",
                "message.delivered",
                "message.bounced",
                "message.complained",
                "message.rejected",
                "message.opened",
                "message.link_clicked",
                "inbox.created",
                "inbox.deleted",
                "domain.verified"
              ]
            }
          },
          "is_active": {
            "type": "boolean"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Custom delivery headers, values masked (write-only)."
          },
          "endpoint_secret_set": {
            "type": "boolean",
            "description": "True when deliveries are also signed with the receiver's own Standard Webhooks secret (see endpoint_secret on create). The secret itself is write-only and never returned.\n"
          },
          "inbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Inboxes this webhook is restricted to. Empty means every inbox."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MetricsBucket": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Bucket start, UTC."
          },
          "sent": {
            "type": "integer"
          },
          "received": {
            "type": "integer"
          },
          "bounced": {
            "type": "integer"
          },
          "complained": {
            "type": "integer"
          },
          "opened": {
            "type": "integer",
            "description": "Messages opened for the first time in this bucket (tracked sends only)."
          },
          "clicked": {
            "type": "integer",
            "description": "Messages whose first link click fell in this bucket (tracked sends only)."
          },
          "webhook_deliveries": {
            "type": "integer",
            "description": "Webhook deliveries that reached the endpoint."
          },
          "webhook_failures": {
            "type": "integer",
            "description": "Deliveries that exhausted their retry budget."
          },
          "injection_flagged": {
            "type": "integer",
            "description": "Inbound messages rated medium or high by the prompt-injection scanner."
          }
        }
      },
      "Metrics": {
        "type": "object",
        "properties": {
          "interval": {
            "type": "string",
            "enum": [
              "day",
              "hour"
            ]
          },
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricsBucket"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/MetricsBucket"
          }
        }
      },
      "Domain": {
        "type": "object",
        "properties": {
          "domain_id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "domain": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "verified",
              "active"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "postmark",
              "ses"
            ],
            "description": "Which service signs and sends this domain's outbound mail. Domains connected from 2026-09-09 use `postmark`; earlier ones remain on `ses`. Determines which DKIM records appear in `dns_records`.\n",
            "example": "postmark"
          },
          "sending_enabled": {
            "type": "boolean",
            "description": "True once the provider has confirmed the domain's DKIM record. Receiving works as soon as MX resolves, but sending from an address on this domain is rejected until this is true.\n"
          },
          "dns_records": {
            "type": "array",
            "description": "Records to publish. Always MX, SPF, DMARC and an ownership TXT; plus the provider's DKIM \u2014 one TXT and a Return-Path CNAME on Postmark, three CNAMEs on SES.\n",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                },
                "priority": {
                  "type": "integer"
                },
                "purpose": {
                  "type": "string"
                }
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "verified_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "description": "RFC 6749 error shape returned by the identity provider endpoints.",
        "properties": {
          "error": {
            "type": "string",
            "example": "invalid_grant"
          },
          "error_description": {
            "type": "string"
          }
        }
      },
      "IdentityClaims": {
        "type": "object",
        "description": "Claims in the id_token and from /userinfo. Which ones appear depends on the granted scopes and on whether the client is registered.",
        "properties": {
          "sub": {
            "type": "string",
            "description": "The inbox_id. Stable for the life of the inbox; use it as the user id."
          },
          "inbox_id": {
            "type": "string"
          },
          "agent": {
            "type": "boolean",
            "description": "Always true."
          },
          "owner_verified": {
            "type": "boolean",
            "description": "True when a verified human owns the account behind the inbox; false for unclaimed agent-signup (trial) accounts."
          },
          "email": {
            "type": "string",
            "description": "The inbox address (scope email)."
          },
          "email_verified": {
            "type": "boolean",
            "description": "Always true (scope email)."
          },
          "name": {
            "type": "string",
            "description": "Inbox display name, falling back to the local part (scope profile)."
          },
          "preferred_username": {
            "type": "string",
            "description": "Local part of the inbox address (scope profile)."
          },
          "org": {
            "type": "string",
            "description": "Account id that owns the inbox (scope org, registered clients)."
          },
          "plan": {
            "type": "string",
            "description": "Account plan (scope org, registered clients).",
            "enum": [
              "trial",
              "free",
              "hobby",
              "pro",
              "scale",
              "enterprise"
            ]
          },
          "owner_email": {
            "type": "string",
            "nullable": true,
            "description": "Verified owner email (scope owner_email, registered clients). Returned from /userinfo only, never inside the id_token. Null when owner_verified is false."
          }
        }
      },
      "IdentityTokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string",
            "description": "Opaque dse_idt_ token for /userinfo. Lives 1 hour."
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "example": 3600
          },
          "id_token": {
            "type": "string",
            "description": "ES256 JWT, verify against /.well-known/jwks.json. Lives 1 hour."
          },
          "scope": {
            "type": "string"
          },
          "refresh_token": {
            "type": "string",
            "description": "dse_idr_ token, 30 days, rotated on every use. Only for registered clients or when offline_access was granted."
          }
        }
      },
      "IdentityClient": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "example": "dse_idc_3f9a1c77b2e04d5a6b8c"
          },
          "client_name": {
            "type": "string"
          },
          "client_uri": {
            "type": "string"
          },
          "logo_uri": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": [
              "none",
              "client_secret_basic",
              "client_secret_post"
            ]
          },
          "scope": {
            "type": "string",
            "description": "Space-separated scopes the client may request."
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "IdentityClientCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/IdentityClient"
          },
          {
            "type": "object",
            "properties": {
              "client_secret": {
                "type": "string",
                "description": "dse_ics_ secret. Shown once; stored hashed. Absent when token_endpoint_auth_method is none."
              },
              "client_secret_expires_at": {
                "type": "integer",
                "description": "0 means the secret does not expire."
              },
              "client_id_issued_at": {
                "type": "integer"
              },
              "warning": {
                "type": "string"
              },
              "issuer": {
                "type": "string",
                "example": "https://id.deadsimple.email"
              },
              "discovery_url": {
                "type": "string",
                "example": "https://id.deadsimple.email/.well-known/openid-configuration"
              }
            }
          }
        ]
      },
      "IdentityClientRegistration": {
        "type": "object",
        "required": [
          "redirect_uris"
        ],
        "properties": {
          "client_name": {
            "type": "string"
          },
          "client_uri": {
            "type": "string"
          },
          "logo_uri": {
            "type": "string"
          },
          "policy_uri": {
            "type": "string"
          },
          "tos_uri": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            },
            "description": "https, loopback http, or app-scheme URLs."
          },
          "scope": {
            "type": "string",
            "default": "openid email profile owner_email org",
            "description": "Any of openid, email, profile, owner_email, org, offline_access. openid is always included."
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": [
              "none",
              "client_secret_basic",
              "client_secret_post"
            ],
            "default": "client_secret_basic"
          }
        }
      },
      "IdentityKey": {
        "type": "object",
        "properties": {
          "kid": {
            "type": "string",
            "description": "RFC 7638 thumbprint prefix. Put it in the assertion's JWS header."
          },
          "inbox_id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "jwk": {
            "type": "object",
            "description": "The enrolled P-256 public key (kty EC, crv P-256, x, y, kid)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "IdentityConnection": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "client_uri": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "first_sign_in_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_sign_in_at": {
            "type": "string",
            "format": "date-time"
          },
          "sign_in_count": {
            "type": "integer"
          }
        }
      },
      "IdentitySignInResult": {
        "type": "object",
        "properties": {
          "redirect_to": {
            "type": "string",
            "description": "The relying party's redirect_uri with code (and state) appended. GET it, following redirects."
          },
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "expires_in": {
            "type": "integer",
            "description": "Seconds until the authorization code expires (300)."
          },
          "next_step": {
            "type": "string"
          }
        }
      },
      "X402Requirement": {
        "type": "object",
        "description": "One accepted way to pay, from the x402 v2 accepts array.",
        "properties": {
          "scheme": {
            "type": "string",
            "example": "exact"
          },
          "network": {
            "type": "string",
            "description": "CAIP-2 id. eip155:8453 (Base), eip155:137 (Polygon) or solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp."
          },
          "amount": {
            "type": "string",
            "description": "Atomic USDC, six decimals. \"1000000\" is $1.00."
          },
          "asset": {
            "type": "string",
            "description": "USDC contract (EVM) or mint (Solana)."
          },
          "payTo": {
            "type": "string"
          },
          "maxTimeoutSeconds": {
            "type": "integer",
            "example": 300
          },
          "extra": {
            "type": "object",
            "description": "EIP-712 domain {name, version} on EVM networks; {feePayer} on Solana."
          }
        }
      },
      "PaymentRequiredBody": {
        "type": "object",
        "description": "Our standard error envelope plus the x402 v2 fields (minus its own error string) so that x402 v1 clients, which read requirements from the body, can pay too.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "payment_required"
              },
              "message": {
                "type": "string"
              },
              "price_usd": {
                "type": "string",
                "example": "1.00"
              },
              "docs": {
                "type": "string",
                "example": "https://deadsimple.email/pay-per-request.html"
              },
              "reason": {
                "type": "string",
                "description": "Present when a submitted payment was rejected (amount mismatch, network not accepted, facilitator invalidReason, declined card, challenge reused)."
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "request_id": {
                "type": "string"
              }
            }
          },
          "x402Version": {
            "type": "integer",
            "example": 2
          },
          "resource": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "mimeType": {
                "type": "string"
              }
            }
          },
          "accepts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/X402Requirement"
            }
          },
          "extensions": {
            "type": "object"
          }
        }
      },
      "PaymentCredentials": {
        "type": "object",
        "description": "Issued once, on a payer's first paid inbox. The API key belongs to the Pay as you go account keyed on the wallet (or created for this card purchase) and has the same scoped permissions as an agent-signup key.",
        "properties": {
          "api_key": {
            "type": "string",
            "description": "Shown once."
          },
          "key_id": {
            "type": "string"
          },
          "account_id": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "warning": {
            "type": "string"
          }
        }
      },
      "PaymentSettlement": {
        "type": "object",
        "description": "How the call was paid. x402 gives {transaction, network, payer}; MPP gives {reference, method}.",
        "properties": {
          "transaction": {
            "type": "string",
            "description": "On-chain transaction (x402)."
          },
          "network": {
            "type": "string",
            "description": "CAIP-2 network (x402)."
          },
          "payer": {
            "type": "string",
            "description": "Payer wallet address (x402)."
          },
          "reference": {
            "type": "string",
            "description": "Stripe PaymentIntent id (MPP)."
          },
          "method": {
            "type": "string",
            "example": "stripe",
            "description": "Payment method (MPP)."
          }
        }
      },
      "InboxCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Inbox"
          },
          {
            "type": "object",
            "properties": {
              "credentials": {
                "$ref": "#/components/schemas/PaymentCredentials"
              },
              "payment": {
                "$ref": "#/components/schemas/PaymentSettlement"
              }
            }
          }
        ]
      },
      "CalendarAttendee": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "response": {
            "type": "string",
            "enum": [
              "needs-action",
              "accepted",
              "declined",
              "tentative"
            ],
            "description": "The attendee's answer as last seen (our own rsvp, or their REPLY)."
          },
          "optional": {
            "type": "boolean",
            "description": "OPT-PARTICIPANT rather than REQ-PARTICIPANT on the invitation."
          }
        }
      },
      "CalendarOrganizer": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CalendarEventInput": {
        "type": "object",
        "description": "Fields for creating or (all optional, on PATCH) updating an event. Times are ISO 8601 and need a zone: a trailing Z, an offset, or `timezone`. A bare date makes an all-day event. Stored and returned as UTC instants.",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 500
          },
          "start": {
            "type": "string",
            "description": "\"2026-09-15T15:00:00Z\", \"2026-09-15T15:00:00-04:00\", \"2026-09-15T15:00:00\" plus timezone, or \"2026-09-15\"."
          },
          "end": {
            "type": "string",
            "description": "Omit to use duration_minutes (default 30). On PATCH, a moved start keeps the event's length."
          },
          "duration_minutes": {
            "type": "integer",
            "minimum": 1
          },
          "timezone": {
            "type": "string",
            "description": "IANA zone for a local start/end with no offset, e.g. America/New_York. Also sets X-WR-TIMEZONE on the feed."
          },
          "all_day": {
            "type": "boolean"
          },
          "description": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "tentative",
              "cancelled"
            ],
            "default": "confirmed"
          },
          "organizer": {
            "$ref": "#/components/schemas/CalendarOrganizer",
            "description": "Defaults to the inbox itself. Only events the inbox organizes can be sent with invite; only events it does not can be answered with rsvp."
          },
          "attendees": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "oneOf": [
                {
                  "type": "string",
                  "format": "email"
                },
                {
                  "$ref": "#/components/schemas/CalendarAttendee"
                }
              ]
            }
          },
          "ical_uid": {
            "type": "string",
            "description": "Create only. Supply your own iCalendar UID; otherwise one is generated as {hex}@deadsimple.email."
          },
          "sequence": {
            "type": "integer",
            "description": "iCalendar SEQUENCE. Managed for you; set it only to take over from a calendar system that already sent this event."
          }
        }
      },
      "CalendarEvent": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string"
          },
          "inbox_id": {
            "type": "string"
          },
          "workspace_id": {
            "type": "string",
            "nullable": true
          },
          "ical_uid": {
            "type": "string",
            "description": "Stable across updates. What an update, cancellation or reply is matched on, on both ends."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "start_at": {
            "type": "string",
            "description": "ISO 8601 UTC, e.g. 2026-09-15T19:00:00Z"
          },
          "end_at": {
            "type": "string",
            "description": "ISO 8601 UTC. Exclusive for all-day events."
          },
          "timezone": {
            "type": "string"
          },
          "all_day": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "tentative",
              "cancelled"
            ]
          },
          "organizer": {
            "$ref": "#/components/schemas/CalendarOrganizer"
          },
          "attendees": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CalendarAttendee"
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "sent",
              "inbound"
            ],
            "description": "api = created here; sent = created here and sent as an invitation; inbound = arrived by email."
          },
          "sequence": {
            "type": "integer"
          },
          "message_id": {
            "type": "string",
            "nullable": true,
            "description": "The invitation we sent, or the inbound message that last created, updated or cancelled the event."
          },
          "invited_at": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "CalendarEventList": {
        "type": "object",
        "properties": {
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CalendarEvent"
            }
          },
          "count": {
            "type": "integer"
          },
          "cursor": {
            "type": "string",
            "description": "Present when there is another page. Pass it back as ?cursor=."
          }
        }
      },
      "CalendarInviteResult": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarEvent"
          },
          {
            "type": "object",
            "properties": {
              "message_id": {
                "type": "string",
                "description": "The sent message."
              },
              "method": {
                "type": "string",
                "enum": [
                  "REQUEST",
                  "CANCEL"
                ],
                "description": "CANCEL when the event's status is cancelled; REQUEST otherwise."
              },
              "sent_to": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        ]
      },
      "CalendarRsvpResult": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarEvent"
          },
          {
            "type": "object",
            "properties": {
              "message_id": {
                "type": "string",
                "description": "The REPLY message sent to the organizer."
              },
              "response": {
                "type": "string",
                "enum": [
                  "accepted",
                  "declined",
                  "tentative"
                ]
              }
            }
          }
        ]
      },
      "CalendarFeed": {
        "type": "object",
        "properties": {
          "inbox_id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "feed_url": {
            "type": "string",
            "description": "https URL of the .ics feed, token included. Paste into Google Calendar (\"From URL\"), Apple Calendar or Outlook."
          },
          "webcal_url": {
            "type": "string",
            "description": "The same feed as a webcal:// link, which most calendar apps open as a subscription."
          },
          "token_created_at": {
            "type": "string"
          },
          "rotated": {
            "type": "boolean",
            "description": "True when this call issued a new token (the first request, or a rotate)."
          }
        }
      }
    }
  },
  "paths": {
    "/v1/health": {
      "get": {
        "summary": "Health check",
        "security": [],
        "tags": [
          "System"
        ],
        "responses": {
          "200": {
            "description": "API is healthy"
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "summary": "OAuth 2.1 authorization server metadata (RFC 8414)",
        "description": "Also served at /.well-known/oauth-authorization-server/mcp.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "responses": {
          "200": {
            "description": "Issuer, endpoint URLs, S256 PKCE, supported grants."
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "summary": "Protected resource metadata for the MCP endpoint (RFC 9728)",
        "description": "Also served at /.well-known/oauth-protected-resource/mcp.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "responses": {
          "200": {
            "description": "Resource identifier and authorization servers."
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "summary": "Dynamic client registration (RFC 7591)",
        "description": "Registers a public OAuth client. redirect_uris must be https, loopback http, or app-scheme URLs. Rate limited per IP.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "client_name": {
                    "type": "string"
                  },
                  "client_uri": {
                    "type": "string"
                  },
                  "logo_uri": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "client_id issued (no client secret \u2014 public client)."
          },
          "400": {
            "description": "invalid_client_metadata or invalid_redirect_uri."
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "summary": "Authorization endpoint (authorization-code + PKCE)",
        "description": "Redirects the user to the consent page at app.deadsimple.email/oauth/consent. code_challenge (S256) is required; the code is bound to the approving account.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "resource",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to consent, or back to redirect_uri with an error."
          },
          "400": {
            "description": "Unknown client or unregistered redirect_uri (never redirected)."
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "summary": "Token endpoint",
        "description": "Exchanges an authorization code (with code_verifier) or a refresh token for tokens. Access tokens (dse_oat_) live 7 days; refresh tokens (dse_ort_) live 90 days and rotate on every use. Accepts application/x-www-form-urlencoded or JSON.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "responses": {
          "200": {
            "description": "access_token, token_type, expires_in, refresh_token, scope."
          },
          "400": {
            "description": "RFC 6749 error shape (invalid_grant, unsupported_grant_type)."
          }
        }
      }
    },
    "/oauth/revoke": {
      "post": {
        "summary": "Token revocation (RFC 7009)",
        "description": "Revokes an access or refresh token. Always returns 200.",
        "security": [],
        "tags": [
          "OAuth"
        ],
        "responses": {
          "200": {
            "description": "Token revoked (or was already unknown)."
          }
        }
      }
    },
    "/.well-known/openid-configuration": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "get": {
        "summary": "OpenID Connect discovery",
        "description": "Issuer, endpoint URLs, supported scopes and claims, ES256, S256 PKCE, and the non-standard `agent_authentication_methods_supported` (api_key, assertion, browser). Cached one hour. Note that the same path on api.deadsimple.email returns the MCP OAuth server's metadata instead.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "responses": {
          "200": {
            "description": "The provider metadata document."
          }
        }
      }
    },
    "/.well-known/jwks.json": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "get": {
        "summary": "JSON Web Key Set",
        "description": "The ES256 (P-256) public key that signs id_tokens. Cached one hour.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "responses": {
          "200": {
            "description": "{ keys: [ { kty: EC, crv: P-256, alg: ES256, use: sig, kid, x, y } ] }"
          }
        }
      }
    },
    "/authorize": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "get": {
        "summary": "Authorization endpoint (authorization-code + PKCE)",
        "description": "Three ways an agent authenticates, checked in this order.\n1. **API key**: send `Authorization: Bearer dse_...` plus `inbox_id=` (or `login_hint=<inbox email>`; both may be omitted when the account has exactly one inbox). The code is minted immediately.\n2. **Signed assertion**: `assertion=` an ES256 JWS over `{iss: inbox_id, sub: inbox_id, aud: \"https://id.deadsimple.email\", iat, exp (at most 10 minutes after iat), jti}` with a `kid` header naming a key enrolled on the inbox. Optional `client_id`, `redirect_uri`, `code_challenge` and `nonce` claims must match the request. Each `jti` is accepted once.\n3. **Browser**: no credential at all redirects to `https://app.deadsimple.email/id/consent?request_id=...`, where the account owner picks an inbox and approves.\nSuccess is a 302 to `redirect_uri` with `code` and `state`, or, when the request sends `Accept: application/json`, a 200 JSON body `{redirect_to, code, state}`. A JSON client with no credential gets `401 login_required` rather than a redirect. An unresolvable client_id or a redirect_uri that is not same-origin (open client) or not registered gets a 400 with no redirect.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "A registered dse_idc_ id, or (open client) an https URL sharing its origin with redirect_uri."
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "openid"
            },
            "description": "openid required. Open clients may add email and profile; registered clients may also add owner_email, org, offline_access."
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "nonce",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Which inbox signs in (API-key path)."
          },
          {
            "name": "login_hint",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "The inbox email address, as an alternative to inbox_id."
          },
          {
            "name": "assertion",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "ES256 JWS signed by an enrolled key (assertion path). Also accepted as `Authorization: Bearer <jws>`."
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to redirect_uri with code and state (or error and state), or to the consent page."
          },
          "200": {
            "description": "With Accept application/json, the redirect as data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "redirect_to": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_client (never redirected), or a validation error from the API-key path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "login_required (JSON client, no credential), or an assertion that failed verification.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "404": {
            "description": "The API key does not own the requested inbox."
          }
        }
      },
      "post": {
        "summary": "Authorization endpoint (form or JSON body)",
        "description": "Identical to GET; parameters may be sent as application/x-www-form-urlencoded or JSON, which keeps a signed assertion out of the URL. Query and body parameters are merged.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_id": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string"
                  },
                  "response_type": {
                    "type": "string",
                    "enum": [
                      "code"
                    ]
                  },
                  "scope": {
                    "type": "string"
                  },
                  "code_challenge": {
                    "type": "string"
                  },
                  "code_challenge_method": {
                    "type": "string",
                    "enum": [
                      "S256"
                    ]
                  },
                  "state": {
                    "type": "string"
                  },
                  "nonce": {
                    "type": "string"
                  },
                  "inbox_id": {
                    "type": "string"
                  },
                  "login_hint": {
                    "type": "string"
                  },
                  "assertion": {
                    "type": "string"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "302": {
            "description": "As for GET."
          },
          "200": {
            "description": "As for GET with Accept application/json."
          },
          "400": {
            "description": "As for GET."
          },
          "401": {
            "description": "As for GET."
          }
        }
      }
    },
    "/token": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "post": {
        "summary": "Token endpoint",
        "description": "Exchanges an authorization code (with `code_verifier`) or a refresh token. Codes are single use and live 5 minutes; a failed exchange burns the code. Client authentication: `client_secret_basic`, `client_secret_post`, or `none` (open clients and registered public clients). Registered clients, and any grant that included `offline_access`, receive a refresh token (30 days, rotated on every use; a reused refresh token is rejected). Accepts application/x-www-form-urlencoded or JSON.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string",
                    "description": "If sent, must match the authorization request."
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "For client_secret_post. Basic auth is also accepted."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request, invalid_grant (bad or reused code, PKCE mismatch, redirect_uri mismatch), or unsupported_grant_type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "invalid_client. Registered clients that require a secret get a WWW-Authenticate Basic challenge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/userinfo": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "get": {
        "summary": "UserInfo endpoint",
        "description": "Send `Authorization: Bearer dse_idt_...`. Returns the claims for the granted scopes. This is the only place `owner_email` is served, and only to registered clients that were granted the owner_email scope.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "responses": {
          "200": {
            "description": "Claims for the agent inbox.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityClaims"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token, with a WWW-Authenticate Bearer challenge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "UserInfo endpoint (POST)",
        "description": "Same as GET.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "responses": {
          "200": {
            "description": "Claims for the agent inbox.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityClaims"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token."
          }
        }
      }
    },
    "/register": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "post": {
        "summary": "Dynamic client registration (RFC 7591)",
        "description": "Registers a relying party that may request `owner_email`, `org` and `offline_access`. Unlike the MCP OAuth server's /oauth/register, this endpoint requires a Dead Simple API key (`Authorization: Bearer dse_...`) with the api_keys.create permission: trial keys from agent self-signup and MCP OAuth tokens are refused, so an anonymous party cannot mint a client that sees owner data. The client_secret is shown once. The same registration with the standard API envelope is available at POST /v1/identity/clients.",
        "tags": [
          "Identity Provider"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdentityClientRegistration"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "client_id (dse_idc_) and, unless token_endpoint_auth_method is none, client_secret (dse_ics_).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityClientCreated"
                }
              }
            }
          },
          "400": {
            "description": "invalid_client_metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "No API key."
          },
          "403": {
            "description": "Key lacks api_keys.create (trial keys), or an MCP OAuth token was used."
          }
        }
      }
    },
    "/revoke": {
      "servers": [
        {
          "url": "https://id.deadsimple.email",
          "description": "Identity provider"
        }
      ],
      "post": {
        "summary": "Token revocation (RFC 7009)",
        "description": "Revokes a dse_idt_ access token or a dse_idr_ refresh token. Always returns 200.",
        "security": [],
        "tags": [
          "Identity Provider"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token revoked (or was already unknown)."
          }
        }
      }
    },
    "/v1/identity/clients": {
      "get": {
        "summary": "List registered identity clients",
        "description": "Relying parties this account registered for Sign in with Dead Simple. Secrets are never returned.",
        "tags": [
          "Identity"
        ],
        "responses": {
          "200": {
            "description": "Clients.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "clients": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IdentityClient"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Register an identity client",
        "description": "Same registration as POST https://id.deadsimple.email/register, wrapped in the standard API envelope for the dashboard and SDKs (`identity.register_client` / `identity.registerClient`). Requires the api_keys.create permission.",
        "tags": [
          "Identity"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdentityClientRegistration"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client created. client_secret is shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityClientCreated"
                }
              }
            }
          },
          "400": {
            "description": "Validation error (redirect_uris missing or malformed, unsupported auth method)."
          },
          "403": {
            "description": "Key lacks api_keys.create, or an MCP OAuth token was used."
          }
        }
      }
    },
    "/v1/identity/clients/{client_id}": {
      "delete": {
        "summary": "Revoke an identity client",
        "description": "The client can no longer start or complete sign-ins.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked."
          },
          "404": {
            "description": "Client not found or not owned by this account."
          }
        }
      }
    },
    "/v1/identity/request/{request_id}": {
      "get": {
        "summary": "Describe a pending browser sign-in request (dashboard consent)",
        "description": "Used by the consent page at app.deadsimple.email/id/consent. Requires a dashboard session; API keys get 403. A request is valid for 10 minutes and is consumed by /v1/identity/approve.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The relying party asking for sign-in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_id": {
                      "type": "string"
                    },
                    "client_id": {
                      "type": "string"
                    },
                    "client_name": {
                      "type": "string"
                    },
                    "client_uri": {
                      "type": "string"
                    },
                    "registered": {
                      "type": "boolean"
                    },
                    "redirect_host": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "inbox_hint": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Not a dashboard session."
          },
          "404": {
            "description": "Request expired or already handled."
          }
        }
      }
    },
    "/v1/identity/approve": {
      "post": {
        "summary": "Approve or deny a browser sign-in request (dashboard consent)",
        "description": "Requires a dashboard session; API keys get 403. Consumes the request and returns the URL the browser should be sent to: redirect_uri with a code (approve) or with error=access_denied (deny).",
        "tags": [
          "Identity"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "request_id",
                  "approve"
                ],
                "properties": {
                  "request_id": {
                    "type": "string"
                  },
                  "inbox_id": {
                    "type": "string",
                    "description": "Required when approving. Must belong to the session's account."
                  },
                  "approve": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ redirect_to }"
          },
          "403": {
            "description": "Not a dashboard session."
          },
          "404": {
            "description": "Request expired or already handled."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/identity/keys": {
      "get": {
        "summary": "List enrolled agent keys",
        "description": "Public keys that may sign assertions for this inbox, with last_used_at per key.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IdentityKey"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Enroll an agent public key",
        "description": "Enrolls a P-256 (secp256r1) public key so the agent can sign in with an ES256 assertion instead of an API key. Accepts a JWK object, a JWK string, or a PEM. A JWK carrying a private component (d) or a key on any other curve is rejected. The same key cannot be enrolled on two inboxes. SDK: `identity.enroll_key` / `identity.enrollKey`.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "public_key"
                ],
                "properties": {
                  "public_key": {
                    "oneOf": [
                      {
                        "type": "object",
                        "description": "JWK with kty EC, crv P-256, x, y"
                      },
                      {
                        "type": "string",
                        "description": "A JWK as a JSON string, or a PEM public key"
                      }
                    ]
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Label, for example \"worker-7\"."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key enrolled. Use kid in the assertion's JWS header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityKey"
                }
              }
            }
          },
          "400": {
            "description": "Not a valid P-256 public key, or private material was sent."
          },
          "409": {
            "description": "This public key is already enrolled on another inbox."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/identity/keys/{kid}": {
      "delete": {
        "summary": "Delete an agent key",
        "description": "Assertions signed by this key are refused from now on. SDK `identity.delete_key` / `identity.deleteKey`.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "404": {
            "description": "Key not found on this inbox."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/identity/connections": {
      "get": {
        "summary": "List apps this inbox has signed in to",
        "description": "One row per relying party, with scope, first and last sign-in, and a count. SDK `identity.connections`.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Connections, most recent first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connections": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IdentityConnection"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/identity/sign-in": {
      "post": {
        "summary": "One-call sign-in helper",
        "description": "Hand over the relying party's authorization URL (the `https://id.deadsimple.email/authorize?...` link a browser would be sent to) and get back the URL to GET to finish signing in as this inbox. Validates the client, redirect_uri, PKCE and scopes exactly as /authorize does, then mints the code. Exposed as `identity.sign_in(inbox_id, authorization_url)` in the Python SDK, `identity.signIn(inboxId, authorizationUrl)` in the Node SDK, and the `sign_in_with_inbox` MCP tool.",
        "tags": [
          "Identity"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "authorization_url"
                ],
                "properties": {
                  "authorization_url": {
                    "type": "string",
                    "description": "Must start with https://id.deadsimple.email/authorize and carry response_type=code and a code_challenge."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The redirect to follow. The code inside it lives 5 minutes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentitySignInResult"
                }
              }
            }
          },
          "400": {
            "description": "Not our authorize URL, unknown client or unregistered redirect_uri, missing PKCE, or an unsupported scope."
          },
          "404": {
            "description": "Inbox not found on this account."
          }
        }
      }
    },
    "/v1/auth/signup": {
      "post": {
        "summary": "Create an account",
        "security": [],
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 8
                  },
                  "name": {
                    "type": "string"
                  },
                  "ref": {
                    "type": "string",
                    "description": "Optional affiliate referral code (from a `https://deadsimple.email/?via={code}` link). Invalid or unknown codes are ignored \u2014 they never fail signup.\n"
                  }
                }
              },
              "example": {
                "email": "dev@example.com",
                "password": "securepass123",
                "name": "Alex"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account created, verification email sent"
          },
          "400": {
            "description": "Validation error"
          },
          "409": {
            "description": "Email already registered"
          }
        }
      }
    },
    "/v1/auth/verify": {
      "post": {
        "summary": "Verify email with code",
        "security": [],
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "code"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Email verified, session token and API key returned"
          }
        }
      }
    },
    "/v1/auth/login": {
      "post": {
        "summary": "Log in",
        "security": [],
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session token returned"
          },
          "401": {
            "description": "Invalid credentials or unverified email"
          }
        }
      }
    },
    "/v1/auth/logout": {
      "post": {
        "summary": "Revoke current session",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "201": {
            "description": "Session revoked"
          }
        }
      }
    },
    "/v1/auth/forgot-password": {
      "post": {
        "summary": "Request password reset code",
        "security": [],
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reset code sent (if email exists)"
          }
        }
      }
    },
    "/v1/auth/reset-password": {
      "post": {
        "summary": "Reset password with code",
        "security": [],
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "code",
                  "new_password"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  },
                  "new_password": {
                    "type": "string",
                    "minLength": 8
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Password updated"
          }
        }
      }
    },
    "/v1/auth/agent-signup": {
      "post": {
        "summary": "Self-serve signup for autonomous agents",
        "security": [],
        "description": "Provisions an account, an API key, and a live inbox in a single unauthenticated call, so an agent can get an email identity with no human in the loop. The ordinary signup flow needs a mailbox to receive a verification code, which a brand-new agent does not have.\n\nThe resulting account is on the `trial` plan: 1 inbox, 10 sends/hour, 25 sends/day, no custom domains. The key it returns is scoped \u2014 it cannot buy domains, change billing, create further API keys, manage the team, or create workspaces.\n\nSignups are limited per client IP (3/hour, 10/day) and by a platform-wide hourly ceiling; when that ceiling is hit the endpoint returns `503 signup_capacity_reached`.\n\nCall `POST /v1/auth/claim` to attach a verified email and move to the Free plan, which lifts the trial send limits.\n",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 24
            },
            "description": "Optional. Random, high-entropy value (a UUID works) that makes a retried signup return the original credentials instead of creating a second account. Treat it as a secret \u2014 for 24 hours it can retrieve this account's API key. Values shorter than 24 characters are rejected.\n"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional name for the agent, used on the inbox and API key."
                  },
                  "ref": {
                    "type": "string",
                    "description": "Optional affiliate referral code. Invalid or unknown codes are ignored \u2014 they never fail signup.\n"
                  }
                }
              },
              "example": {
                "label": "research-bot"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account, API key, and inbox provisioned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account_id": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string",
                      "description": "Shown once. Send as `Authorization: Bearer <api_key>`."
                    },
                    "key_id": {
                      "type": "string"
                    },
                    "inbox": {
                      "type": "object",
                      "properties": {
                        "inbox_id": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    },
                    "plan": {
                      "type": "object"
                    },
                    "next_steps": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Idempotency-Key supplied but too short"
          },
          "429": {
            "description": "Per-IP signup limit reached"
          },
          "503": {
            "description": "Platform-wide signup capacity reached; retry shortly"
          }
        }
      }
    },
    "/v1/auth/claim": {
      "post": {
        "summary": "Start claiming an agent account with a real email",
        "description": "Sends a verification code to `email`. Authenticated with the agent's own trial API key, so only the holder of that key can begin a claim.\n",
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              },
              "example": {
                "email": "operator@company.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Verification code sent"
          },
          "400": {
            "description": "Invalid/disposable email, email already registered, or account already claimed"
          },
          "429": {
            "description": "Too many claim attempts for this account"
          }
        }
      }
    },
    "/v1/auth/claim/verify": {
      "post": {
        "summary": "Finish claiming an agent account (trial -> free)",
        "description": "Confirms the code and upgrades the account to the Free plan. The account_id, API key, inboxes and message history are all preserved; only the owner identity and the plan change, and the trial send limits stop applying.\n",
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "code"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "code": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 8,
                    "description": "Optional dashboard password. If omitted, use POST /v1/auth/forgot-password to set one later.\n"
                  }
                }
              },
              "example": {
                "email": "operator@company.com",
                "code": "123456"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account claimed and upgraded to Free"
          },
          "400": {
            "description": "Invalid or expired code, or account already claimed"
          },
          "409": {
            "description": "Email already registered to another account"
          }
        }
      }
    },
    "/v1/auth/me": {
      "get": {
        "summary": "Get current account info",
        "tags": [
          "Auth"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Account and user info"
          }
        }
      }
    },
    "/v1/team": {
      "get": {
        "summary": "List team members",
        "tags": [
          "Team"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "List of team members with roles"
          }
        }
      }
    },
    "/v1/team/invite": {
      "post": {
        "summary": "Invite a user to the team",
        "description": "Requires admin or owner role. Sends an invitation email.",
        "tags": [
          "Team"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "viewer",
                      "developer",
                      "admin"
                    ],
                    "default": "developer"
                  }
                }
              },
              "example": {
                "email": "teammate@company.com",
                "role": "developer"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invitation created"
          }
        }
      }
    },
    "/v1/team/{user_id}/role": {
      "put": {
        "summary": "Change a member's role",
        "description": "Requires admin or owner. Only owner can promote to owner.",
        "tags": [
          "Team"
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "role"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "viewer",
                      "developer",
                      "admin",
                      "owner"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role updated"
          }
        }
      }
    },
    "/v1/team/{user_id}": {
      "delete": {
        "summary": "Remove a member from the team",
        "description": "Requires admin or owner. Cannot remove the account owner.",
        "tags": [
          "Team"
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Member removed"
          }
        }
      }
    },
    "/v1/api-keys": {
      "post": {
        "summary": "Create API key",
        "tags": [
          "API Keys"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "permissions": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Legacy scopes (read, write, admin) or granular permissions (resource.operation). Legacy scopes expand automatically \u2014 \"read\" grants all *.read permissions, \"write\" grants read + create/update/delete/send, \"admin\" grants everything. Granular examples: inboxes.read, messages.send, webhooks.create.\n"
                  },
                  "workspace_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional workspace ID to create a workspace-scoped API key"
                  },
                  "inbox_ids": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Optional inbox scope. The key can then only see and act on these inboxes: any other inbox of the account answers 404, account-wide listings (GET /v1/inboxes, /v1/messages, /v1/threads, /v1/metrics) are filtered to them, and the key cannot create inboxes. Every id must belong to the account (and to workspace_id when both are given). An inbox-scoped key may only mint keys scoped to a subset of its own inboxes. Keys without inbox_ids behave as before.\n"
                  }
                }
              },
              "example": {
                "name": "Production Key",
                "permissions": [
                  "read",
                  "write"
                ],
                "inbox_ids": [
                  "b1a7f2c0-3f44-4c2b-9d0e-6a1e2f3c4d5e"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created (key shown once). Includes `inbox_ids` (empty when unscoped)."
          }
        }
      },
      "get": {
        "summary": "List API keys",
        "tags": [
          "API Keys"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "List of API keys (without secrets)"
          }
        }
      }
    },
    "/v1/api-keys/{key_id}": {
      "get": {
        "summary": "Get API key",
        "description": "One key's metadata (name, permissions, workspace_id, inbox_ids). Never the secret.",
        "tags": [
          "API Keys"
        ],
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "API key (without secret)"
          },
          "404": {
            "description": "No such key on this account"
          }
        }
      },
      "delete": {
        "summary": "Revoke API key",
        "tags": [
          "API Keys"
        ],
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Key revoked"
          }
        }
      }
    },
    "/v1/inboxes": {
      "post": {
        "summary": "Create inbox",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "type": "string"
                  },
                  "domain": {
                    "type": "string",
                    "default": "deadsimple.email"
                  },
                  "local_part": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "display_name": "Support Bot",
                "tags": [
                  "support",
                  "bot"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Inbox created with email address. When paid per request, the response also carries a payment header and, on a payer's first inbox, `credentials`.",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "x402 settlement, base64 JSON {success, transaction, network, payer}. Also sent as X-PAYMENT-RESPONSE.",
                "schema": {
                  "type": "string"
                }
              },
              "X-PAYMENT-RESPONSE": {
                "description": "Same value as PAYMENT-RESPONSE, for x402 v1 clients.",
                "schema": {
                  "type": "string"
                }
              },
              "Payment-Receipt": {
                "description": "Stripe MPP receipt, base64url JCS JSON {method \"stripe\", reference \"pi_...\", status \"success\", timestamp, amount (cents), currency}.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/InboxCreated"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          }
        }
      },
      "get": {
        "summary": "List inboxes",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "workspace_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter inboxes by workspace"
          },
          {
            "name": "domain",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused"
              ]
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Paginated list of inboxes"
          }
        }
      }
    },
    "/v1/inboxes/bulk": {
      "post": {
        "summary": "Bulk create inboxes",
        "description": "Create up to 100 inboxes in one call. Returns a per-inbox result.",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "inboxes"
                ],
                "properties": {
                  "inboxes": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "display_name": {
                          "type": "string"
                        },
                        "local_part": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "tags": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-inbox creation results with created/failed/total counts"
          }
        }
      },
      "delete": {
        "summary": "Bulk delete inboxes",
        "description": "Delete up to 100 inboxes in one call. Returns a per-inbox result.",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "inbox_ids"
                ],
                "properties": {
                  "inbox_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "inbox_ids": [
                  "inbox_abc",
                  "inbox_def"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-inbox deletion results with deleted/failed/total counts"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}": {
      "get": {
        "summary": "Get inbox",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Inbox details"
          }
        }
      },
      "patch": {
        "summary": "Update inbox",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated inbox"
          }
        }
      },
      "delete": {
        "summary": "Delete inbox",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Inbox deleted and mailbox deprovisioned"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/verification": {
      "get": {
        "summary": "Get latest verification code / magic link",
        "description": "Agent self-onboarding in one call. Returns the one-time code (OTP) or magic link from the most recent inbound message in this inbox, so an agent can sign up for a service or complete 2FA without parsing email bodies \u2014 from any language, no MCP required. Non-blocking: it scans recent inbound mail and returns immediately (found=false if nothing has arrived yet), so poll it on a short interval after triggering the signup.\n",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "from_contains",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only consider messages whose from address contains this substring."
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Ignore messages received before this ISO-8601 timestamp. Pass the moment you triggered the signup to avoid returning a stale code.\n"
          },
          {
            "name": "window",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            },
            "description": "Max recent inbound messages to scan (1\u201350)."
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "The extracted verification data, or found=false if none yet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "found": {
                      "type": "boolean"
                    },
                    "verification_code": {
                      "type": "string",
                      "nullable": true
                    },
                    "magic_link_url": {
                      "type": "string",
                      "nullable": true
                    },
                    "expires_in": {
                      "type": "string",
                      "nullable": true
                    },
                    "message_id": {
                      "type": "string"
                    },
                    "from_email": {
                      "type": "string"
                    },
                    "received_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages": {
      "get": {
        "summary": "List messages",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "labels",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated labels to filter by (e.g. \"state:unreplied,priority:high\")"
          },
          {
            "name": "include_spam",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Include messages flagged as spam (excluded by default)"
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Paginated list of messages"
          }
        }
      },
      "post": {
        "summary": "Send email",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "to",
                  "subject"
                ],
                "properties": {
                  "to": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  },
                  "subject": {
                    "type": "string"
                  },
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  },
                  "cc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "bcc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Schedule send for a future time (ISO 8601)"
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Labels to attach to the message on creation"
                  },
                  "reply_to": {
                    "type": "string"
                  },
                  "headers": {
                    "type": "object"
                  },
                  "tracking": {
                    "type": "boolean",
                    "default": false,
                    "description": "Enable open/click tracking (HTML emails only)"
                  },
                  "template_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Render a template instead of using body fields"
                  },
                  "variables": {
                    "type": "object",
                    "description": "Template variable substitutions"
                  },
                  "in_reply_to": {
                    "type": "string",
                    "description": "Parent message to thread onto. Accepts either a message_id from this inbox or a raw Message-ID header.\n"
                  },
                  "references": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Message-ID headers for threading"
                  },
                  "attachments": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string"
                        },
                        "content_type": {
                          "type": "string"
                        },
                        "data": {
                          "type": "string",
                          "description": "Base64-encoded file content"
                        }
                      }
                    }
                  },
                  "calendar_invite": {
                    "$ref": "#/components/schemas/CalendarInvite"
                  }
                }
              },
              "example": {
                "to": [
                  "user@example.com"
                ],
                "subject": "Hello from my AI agent",
                "text_body": "This email was sent programmatically.",
                "tracking": false
              }
            }
          }
        },
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Email sent"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}": {
      "get": {
        "summary": "Get message with full body",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Full message with body, headers, attachments"
          }
        }
      },
      "patch": {
        "summary": "Update message labels",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "add_labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Labels to add to the message"
                  },
                  "remove_labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Labels to remove from the message"
                  }
                }
              },
              "example": {
                "add_labels": [
                  "state:unreplied",
                  "priority:high"
                ],
                "remove_labels": [
                  "state:new"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated message with labels"
          }
        }
      },
      "delete": {
        "summary": "Delete a message",
        "description": "Removes the message from every read at once: lists, search, threads, attachments, the SSE stream, and the IMAP mailbox copy. The message is purged for good 30 days later and cannot be restored. Sent mail keeps counting toward the monthly quota and the per-inbox daily cap, since those count what was sent. Needs `messages.delete`.\n",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "example": {
                  "message_id": "4c2d7a8e-1f3b-4e6a-9d0c-8b5a2f1e7c93",
                  "deleted": true
                }
              }
            }
          },
          "404": {
            "description": "No such message in this inbox, or already deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/scheduled": {
      "get": {
        "summary": "List scheduled messages",
        "description": "Messages sent with `send_at` that have not gone out yet, soonest first. At `send_at` the original request is sent through the normal send path, so quota, abuse and guardrail checks run at that moment; a message they refuse ends with status `failed` and a `failure_reason`.\n",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Pending scheduled messages",
            "content": {
              "application/json": {
                "example": {
                  "scheduled": [
                    {
                      "message_id": "7d1c2b3a-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                      "send_at": "2026-10-02T09:00:00Z",
                      "to": [
                        "dana@example.com"
                      ],
                      "subject": "Following up",
                      "created_at": "2026-10-01T15:12:40Z"
                    }
                  ],
                  "count": 1
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/cancel": {
      "post": {
        "summary": "Cancel a scheduled message",
        "description": "Stops a message scheduled with `send_at` from going out; its status becomes `cancelled`. 409 once it has been sent (or was already cancelled). To change the time or content, cancel and schedule again.\n",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled",
            "content": {
              "application/json": {
                "example": {
                  "message_id": "7d1c2b3a-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                  "status": "cancelled"
                }
              }
            }
          },
          "409": {
            "description": "Not waiting to be sent"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/reply": {
      "post": {
        "summary": "Reply to a message",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  },
                  "to": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Override the recipients. Defaults to the other side of the conversation: the sender for a message you received, the original recipients for one you sent.\n"
                  },
                  "cc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Additional CC recipients. On reply-all these are added to the original participants.\n"
                  },
                  "bcc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Schedule the reply for a future time (ISO 8601) instead of sending it now.\n"
                  },
                  "calendar_invite": {
                    "$ref": "#/components/schemas/CalendarInvite"
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Reply sent with threading headers auto-set"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/reply-all": {
      "post": {
        "summary": "Reply-all to a message",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  },
                  "to": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Override the recipients. Defaults to the other side of the conversation: the sender for a message you received, the original recipients for one you sent.\n"
                  },
                  "cc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Additional CC recipients. On reply-all these are added to the original participants.\n"
                  },
                  "bcc": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Schedule the reply for a future time (ISO 8601) instead of sending it now.\n"
                  },
                  "calendar_invite": {
                    "$ref": "#/components/schemas/CalendarInvite"
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Reply-all sent"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/forward": {
      "post": {
        "summary": "Forward a message",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "to"
                ],
                "properties": {
                  "to": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Message forwarded"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}": {
      "get": {
        "summary": "Get attachment download URL",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Signed download URL (expires in 1 hour)"
          }
        }
      }
    },
    "/v1/threads": {
      "get": {
        "summary": "List threads across all inboxes (org-wide)",
        "description": "Returns threads from every inbox in the account. Useful for supervisor agents monitoring multiple agent conversations.",
        "tags": [
          "Threads"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter to threads from a specific inbox"
          },
          {
            "name": "labels",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated labels to filter by"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Thread summaries across all inboxes"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/threads": {
      "get": {
        "summary": "List threads in an inbox",
        "tags": [
          "Threads"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Thread summaries with latest message"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/threads/{thread_id}": {
      "get": {
        "summary": "Get thread with all messages",
        "tags": [
          "Threads"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thread_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "All messages in the thread, chronological"
          }
        }
      },
      "delete": {
        "summary": "Delete a thread",
        "description": "Deletes every message of the thread in this inbox, with the same behaviour as deleting each message. Needs `threads.delete`.\n",
        "tags": [
          "Threads"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thread_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "example": {
                  "thread_id": "9a1e5c3b-7d2f-4b8a-a6e0-3c9f1d7b5e24",
                  "deleted": true,
                  "messages_deleted": 4
                }
              }
            }
          },
          "404": {
            "description": "No such thread in this inbox"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/threads/{thread_id}/attachments": {
      "get": {
        "summary": "Get all attachments in a thread",
        "tags": [
          "Threads"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thread_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "All attachments across every message in the thread, with message_id attribution"
          }
        }
      }
    },
    "/v1/domains": {
      "post": {
        "summary": "Add custom domain",
        "tags": [
          "Domains"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "domain": "mail.yourcompany.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Domain added with DNS records to configure"
          }
        }
      },
      "get": {
        "summary": "List domains",
        "tags": [
          "Domains"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "workspace_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter domains by workspace"
          }
        ],
        "responses": {
          "200": {
            "description": "List of custom domains"
          }
        }
      }
    },
    "/v1/domains/{domain_id}/verify": {
      "get": {
        "summary": "Verify domain DNS records",
        "tags": [
          "Domains"
        ],
        "parameters": [
          {
            "name": "domain_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "DNS verification status"
          }
        }
      }
    },
    "/v1/domains/{domain_id}": {
      "delete": {
        "summary": "Remove domain",
        "tags": [
          "Domains"
        ],
        "parameters": [
          {
            "name": "domain_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Domain removed"
          }
        }
      }
    },
    "/v1/attachments": {
      "post": {
        "summary": "Stage an outbound attachment",
        "description": "Reserve an attachment_id and a presigned S3 URL, then PUT the bytes to that URL and reference the id when sending. Two steps by necessity: a send request cannot carry more than a few megabytes, which is less than one phone photo. The same attachment_id can be attached to any number of messages without re-uploading, and expires after 7 days if unused.\n",
        "tags": [
          "Messages"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename"
                ],
                "properties": {
                  "filename": {
                    "type": "string"
                  },
                  "content_type": {
                    "type": "string",
                    "description": "Guessed from the file extension when omitted."
                  },
                  "size": {
                    "type": "integer",
                    "description": "Optional; rejected up front if over the limit."
                  }
                }
              },
              "example": {
                "filename": "door-damage.jpg",
                "content_type": "image/jpeg"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Attachment staged; PUT the bytes to upload_url",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "attachment_id": {
                      "type": "string"
                    },
                    "upload_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "max_bytes": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "summary": "Register webhook",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "message.received",
                        "message.sent",
                        "message.delivered",
                        "message.bounced",
                        "message.complained",
                        "message.rejected",
                        "message.opened",
                        "message.link_clicked",
                        "inbox.created",
                        "inbox.deleted",
                        "domain.verified"
                      ]
                    }
                  },
                  "description": {
                    "type": "string"
                  },
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "maxProperties": 10,
                    "description": "Optional custom headers sent on every delivery attempt and every retry \u2014 for endpoints that enforce their own auth (Bearer tokens, gateway keys). Values are write-only and are masked in every response. Reserved names (Content-Type, Host, User-Agent, hop-by-hop headers, and any `X-DSE-*` header) are rejected, as are values with control characters or non-ASCII bytes. Max 10 headers, 1024 characters per value.\n"
                  },
                  "endpoint_secret": {
                    "type": "string",
                    "pattern": "^whsec_[A-Za-z0-9+/]+={0,2}$",
                    "description": "The receiving service's own Standard Webhooks secret (`whsec_...`), for endpoints that verify every request against it, such as Grok Automations. Each delivery then also carries `webhook-id` (the delivery id, stable across retries), `webhook-timestamp` and `webhook-signature` (`v1,<base64 HMAC-SHA256 of \"id.timestamp.body\">`) per standardwebhooks.com. Such receivers answer an unsigned request with HTTP 400. Write-only. A `whsec_` value supplied as `Authorization: Bearer whsec_...` in headers is treated the same way and not sent as a header.\n"
                  },
                  "inbox_ids": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Optional inbox scope. A webhook with inbox_ids fires only for events whose payload names one of those inboxes (so never for inbox-less events such as domain.verified). Every id must belong to the account. Omit or pass an empty list for an account-wide webhook. An inbox-scoped API key may only register webhooks for its own inboxes and gets them by default.\n"
                  }
                }
              },
              "example": {
                "url": "https://your-app.com/webhooks/email",
                "events": [
                  "message.received"
                ],
                "description": "Notify on new inbound email",
                "inbox_ids": [
                  "b1a7f2c0-3f44-4c2b-9d0e-6a1e2f3c4d5e"
                ],
                "headers": {
                  "Authorization": "Bearer eyJhbGciOi..."
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created with signing secret (shown once)"
          }
        }
      },
      "get": {
        "summary": "List webhooks",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "workspace_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter webhooks by workspace"
          }
        ],
        "responses": {
          "200": {
            "description": "List of webhooks"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}": {
      "get": {
        "summary": "Get webhook",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook (signing secret never returned; header values masked)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "404": {
            "description": "No such webhook on this account"
          }
        }
      },
      "patch": {
        "summary": "Update webhook",
        "description": "Partial update. Any of url, events, description, inbox_ids, is_active and endpoint_secret may be supplied; unknown fields are ignored and at least one known field is required. `inbox_ids: []` clears the inbox scope. Setting `is_active` to true also resets the consecutive-failure counter, so an auto-disabled endpoint starts over with a full disable budget.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "description": {
                    "type": "string"
                  },
                  "inbox_ids": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "is_active": {
                    "type": "boolean"
                  },
                  "endpoint_secret": {
                    "type": "string",
                    "pattern": "^whsec_[A-Za-z0-9+/]+={0,2}$",
                    "description": "The receiving service's own Standard Webhooks secret (`whsec_...`), for endpoints that verify every request against it, such as Grok Automations. Each delivery then also carries `webhook-id` (the delivery id, stable across retries), `webhook-timestamp` and `webhook-signature` (`v1,<base64 HMAC-SHA256 of \"id.timestamp.body\">`) per standardwebhooks.com. Such receivers answer an unsigned request with HTTP 400. Write-only. A `whsec_` value supplied as `Authorization: Bearer whsec_...` in headers is treated the same way and not sent as a header. `null` removes it.\n"
                  }
                }
              },
              "example": {
                "inbox_ids": [
                  "b1a7f2c0-3f44-4c2b-9d0e-6a1e2f3c4d5e"
                ],
                "is_active": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Invalid field, unknown inbox, or nothing to update"
          }
        }
      },
      "delete": {
        "summary": "Delete webhook",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Webhook deleted"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/config": {
      "get": {
        "summary": "Get webhook retry configuration",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Retry/backoff configuration"
          }
        }
      },
      "put": {
        "summary": "Update webhook retry configuration",
        "description": "Tune delivery reliability. `retry_schedule` is the exponential-backoff delay (seconds) before each retry; failed deliveries are retried by the webhook-retry processor until `max_retries` is reached. Endpoints that fail `disable_on_failures` times in a row are auto-disabled.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "max_retries": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10
                  },
                  "retry_schedule": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "timeout_seconds": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 60
                  },
                  "disable_on_failures": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              "example": {
                "max_retries": 6,
                "retry_schedule": [
                  1,
                  30,
                  300,
                  1800,
                  7200,
                  86400
                ],
                "timeout_seconds": 30,
                "disable_on_failures": 50
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated configuration"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/headers": {
      "get": {
        "summary": "Get webhook custom delivery headers",
        "description": "Header names installed on the webhook. Values are masked.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Custom headers (values masked)"
          }
        }
      },
      "put": {
        "summary": "Replace webhook custom delivery headers",
        "description": "Replaces the webhook's custom headers wholesale; send `{\"headers\": {}}` to clear them. These headers are sent on every delivery attempt and every retry, so an endpoint that requires its own `Authorization` header can be used without polling. Values are write-only \u2014 responses mask them.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "headers"
                ],
                "properties": {
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "maxProperties": 10
                  }
                }
              },
              "example": {
                "headers": {
                  "Authorization": "Bearer eyJhbGciOi..."
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated headers (values masked)"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/deliveries": {
      "get": {
        "summary": "List webhook deliveries",
        "description": "Delivery log for a webhook (newest first). Each entry records the event, status (pending/delivered/failed), attempt count, last HTTP status and error, and next scheduled retry.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent delivery attempts"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/deliveries/{delivery_id}": {
      "get": {
        "summary": "Get a webhook delivery",
        "description": "A single delivery record, including the payload that was (or will be) sent.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery record"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/replay": {
      "post": {
        "summary": "Replay a webhook delivery",
        "description": "Re-attempt a delivery immediately, e.g. after fixing a broken endpoint. The retry budget is reset so the full backoff schedule is available again.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery re-attempted"
          }
        }
      }
    },
    "/v1/event-subscriptions": {
      "post": {
        "summary": "Create or refresh an MCP Events subscription",
        "description": "Backs `events/subscribe` on the hosted MCP server (OpenAI's MCP Events, used by ChatGPT Work chats and dots). Idempotent: the subscription id is derived from the account, callback URL, event name and arguments, so the same request refreshes the same subscription. A new subscription, or one whose secret changed, is activated only after the callback answers a signed `{\"type\":\"verification\",\"challenge\":...}` POST by echoing the challenge. Events are then POSTed as `{eventId, name, timestamp, data, cursor}` with Standard Webhooks headers (`webhook-id` = eventId, stable across retries) and `X-MCP-Subscription-Id`. 410 and 413 responses are not retried; a 410 deletes the subscription. Field names follow the MCP Events spec.\n",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "delivery"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "enum": [
                      "message.received",
                      "message.bounced"
                    ]
                  },
                  "arguments": {
                    "type": "object",
                    "additionalProperties": false,
                    "description": "Filters. `inbox_id` (both events; omitted = every inbox the credential can see, required for inbox-scoped keys), `from_contains` and `subject_contains` (message.received only, case-insensitive substrings).\n",
                    "properties": {
                      "inbox_id": {
                        "type": "string"
                      },
                      "from_contains": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "subject_contains": {
                        "type": "string",
                        "maxLength": 200
                      }
                    }
                  },
                  "delivery": {
                    "type": "object",
                    "required": [
                      "url",
                      "secret"
                    ],
                    "properties": {
                      "mode": {
                        "type": "string",
                        "enum": [
                          "webhook"
                        ]
                      },
                      "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "HTTPS callback; must resolve to public addresses."
                      },
                      "secret": {
                        "type": "string",
                        "description": "Standard Webhooks secret, `whsec_` + base64 of 24-64 bytes."
                      }
                    }
                  },
                  "ttlMs": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Requested lifetime. Omitted = 30 days; capped at 90 days; null (no expiry) is granted as 90 days.\n"
                  },
                  "cursor": {
                    "description": "Accepted and ignored; these events are not replayable."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription active",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "sub_3f0c2a9d4b1e8f7a6c5d4e3f2a1b0c9d"
                    },
                    "refreshBefore": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "cursor": {
                      "type": "null"
                    },
                    "truncated": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown event, unknown argument, bad secret or callback URL"
          },
          "422": {
            "description": "`callback_verification_failed`: the callback did not echo the challenge. `details[0].reason` is `challenge_failed` or `timeout`.\n"
          }
        }
      },
      "get": {
        "summary": "List MCP Events subscriptions",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "The account's subscriptions (callback host only, never the secret)"
          }
        }
      }
    },
    "/v1/event-subscriptions/unsubscribe": {
      "post": {
        "summary": "Remove an MCP Events subscription by identity",
        "description": "Backs `events/unsubscribe`. Idempotent; removing one that does not exist succeeds.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "delivery"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "arguments": {
                    "type": "object"
                  },
                  "delivery": {
                    "type": "object",
                    "properties": {
                      "url": {
                        "type": "string",
                        "format": "uri"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Removed (empty object)"
          }
        }
      }
    },
    "/v1/event-subscriptions/{subscription_id}": {
      "delete": {
        "summary": "Delete an MCP Events subscription",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "subscription_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted"
          },
          "404": {
            "description": "No such subscription on this account"
          }
        }
      }
    },
    "/v1/filters": {
      "post": {
        "summary": "Create organization-level filter",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action",
                  "criteria",
                  "value"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "receive-allow",
                      "receive-block",
                      "send-allow",
                      "send-block",
                      "reply-allow",
                      "reply-block",
                      "allow",
                      "block"
                    ]
                  },
                  "criteria": {
                    "type": "string",
                    "enum": [
                      "email",
                      "domain",
                      "pattern",
                      "keyword"
                    ]
                  },
                  "value": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "action": "receive-block",
                "criteria": "domain",
                "value": "spam-domain.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Organization-level filter created"
          }
        }
      },
      "get": {
        "summary": "List organization-level filters",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "List of organization-level filters"
          }
        }
      }
    },
    "/v1/filters/{filter_id}": {
      "delete": {
        "summary": "Delete organization-level filter",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "name": "filter_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Filter deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/filters": {
      "post": {
        "summary": "Create inbox-level filter",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action",
                  "criteria",
                  "value"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "receive-allow",
                      "receive-block",
                      "send-allow",
                      "send-block",
                      "reply-allow",
                      "reply-block",
                      "allow",
                      "block"
                    ]
                  },
                  "criteria": {
                    "type": "string",
                    "enum": [
                      "email",
                      "domain",
                      "pattern",
                      "keyword"
                    ]
                  },
                  "value": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Inbox-level filter created"
          }
        }
      },
      "get": {
        "summary": "List inbox-level filters",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "List of inbox-level filters"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/filters/{filter_id}": {
      "delete": {
        "summary": "Delete inbox-level filter",
        "tags": [
          "Filters"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Filter deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/messages/{message_id}/tracking": {
      "get": {
        "summary": "Get open/click tracking stats",
        "tags": [
          "Tracking"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Tracking statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/TrackingStats"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/t/o/{tracking_id}": {
      "get": {
        "summary": "Tracking pixel (records email open)",
        "security": [],
        "tags": [
          "Tracking"
        ],
        "parameters": [
          {
            "name": "tracking_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "1x1 transparent GIF",
            "content": {
              "image/gif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/t/c/{tracking_id}": {
      "get": {
        "summary": "Click redirect (records link click)",
        "security": [],
        "tags": [
          "Tracking"
        ],
        "parameters": [
          {
            "name": "tracking_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Original URL to redirect to"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to original URL"
          }
        }
      }
    },
    "/v1/workspaces": {
      "post": {
        "summary": "Create workspace",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "name": "Production",
                "description": "Production environment inboxes"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Workspace created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List workspaces",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "List of workspaces",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkspaceList"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{workspace_id}": {
      "get": {
        "summary": "Get workspace details",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace details including inbox_count",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update workspace",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Workspace updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete workspace",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "204": {
            "description": "Workspace deleted (cannot delete default workspace)"
          },
          "400": {
            "description": "Cannot delete the default workspace"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Get usage metrics",
        "tags": [
          "Usage"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Current billing period usage stats"
          }
        }
      }
    },
    "/v1/metrics": {
      "get": {
        "summary": "Metrics time series",
        "description": "Activity bucketed into fixed UTC intervals: messages sent and received, bounces, complaints, first opens and first clicks of tracked sends, webhook deliveries and terminal failures, and inbound messages the prompt-injection scanner flagged (medium or high). Derived live from the account's rows; outcomes are attributed to messages created inside the window, and opens/clicks count once per message. Requires `usage.read`. Honours workspace scoping and inbox-scoped API keys.\n",
        "tags": [
          "Usage"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Start of the window, inclusive. ISO date (`2026-09-01`) or datetime (`2026-09-01T12:00:00Z`; naive means UTC). Default: 30 days before `to`.\n"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "End of the window, exclusive. A date-only value means the end of that day, so `from=2026-09-01&to=2026-09-07` is seven whole days. Default: now. The window may span at most 92 days.\n"
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "hour"
              ],
              "default": "day"
            },
            "description": "Bucket size. `hour` is allowed only for windows of 7 days or less."
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated inbox ids (max 100) to restrict the series to. Each must belong to the account and be visible to the key; otherwise 404.\n"
          }
        ],
        "responses": {
          "200": {
            "description": "Bucketed series plus totals over the whole window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Metrics"
                },
                "example": {
                  "interval": "day",
                  "from": "2026-09-01T00:00:00Z",
                  "to": "2026-09-03T00:00:00Z",
                  "series": [
                    {
                      "start": "2026-09-01T00:00:00Z",
                      "sent": 42,
                      "received": 17,
                      "bounced": 1,
                      "complained": 0,
                      "opened": 12,
                      "clicked": 4,
                      "webhook_deliveries": 59,
                      "webhook_failures": 0,
                      "injection_flagged": 2
                    },
                    {
                      "start": "2026-09-02T00:00:00Z",
                      "sent": 38,
                      "received": 21,
                      "bounced": 0,
                      "complained": 0,
                      "opened": 9,
                      "clicked": 3,
                      "webhook_deliveries": 59,
                      "webhook_failures": 1,
                      "injection_flagged": 0
                    }
                  ],
                  "totals": {
                    "sent": 80,
                    "received": 38,
                    "bounced": 1,
                    "complained": 0,
                    "opened": 21,
                    "clicked": 7,
                    "webhook_deliveries": 118,
                    "webhook_failures": 1,
                    "injection_flagged": 2
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad window (from after to, over 92 days, hour over 7 days, unparseable date) or interval"
          },
          "404": {
            "description": "An inbox in `inbox_id` is not visible to this key"
          }
        }
      }
    },
    "/v1/deliverability": {
      "get": {
        "summary": "Deliverability report",
        "description": "Aggregated delivery outcomes for outbound mail over a time window \u2014 delivery, bounce, and complaint rates for the whole account/workspace, broken down per inbox and per sending domain, plus a hard/soft bounce breakdown and suppressed-address count. See exactly what's landing without dedicated IPs or infra to manage.\n",
        "tags": [
          "Usage"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 30
            },
            "description": "Lookback window in days (1\u201390)."
          },
          {
            "name": "inbox_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Restrict the report to a single inbox."
          },
          {
            "name": "domain",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Restrict the report to a single sending domain."
          }
        ],
        "responses": {
          "200": {
            "description": "Deliverability aggregates for the window.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "period": {
                      "type": "object",
                      "properties": {
                        "days": {
                          "type": "integer"
                        },
                        "since": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "until": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "totals": {
                      "type": "object",
                      "description": "Status counts plus total, delivery_rate, bounce_rate, complaint_rate."
                    },
                    "bounce_breakdown": {
                      "type": "object",
                      "properties": {
                        "hard": {
                          "type": "integer"
                        },
                        "soft": {
                          "type": "integer"
                        },
                        "by_subtype": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "by_inbox": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "by_domain": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "suppressed_addresses": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "get": {
        "summary": "List messages across all inboxes (workspace-wide)",
        "description": "For supervisor agents monitoring every inbox in a workspace.",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of messages"
          }
        }
      }
    },
    "/v1/messages/{message_id}": {
      "get": {
        "summary": "Get a message by id (workspace-wide lookup)",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Message"
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/drafts": {
      "post": {
        "summary": "Create a draft",
        "description": "Store a draft for human-in-the-loop review before sending. Supports reply drafts via reply_to_message_id.\n",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "subject": {
                    "type": "string"
                  },
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  },
                  "reply_to_message_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft created"
          }
        }
      },
      "get": {
        "summary": "List drafts",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of drafts"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/drafts/{draft_id}": {
      "get": {
        "summary": "Get a draft",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft"
          }
        }
      },
      "put": {
        "summary": "Update a draft",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated draft"
          }
        }
      },
      "delete": {
        "summary": "Delete a draft",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Draft deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/drafts/{draft_id}/send": {
      "post": {
        "summary": "Send a draft",
        "description": "Send a previously-created draft (e.g. after human approval).",
        "tags": [
          "Drafts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "draft_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft sent"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/guardrails": {
      "get": {
        "summary": "Get inbox agent guardrails",
        "description": "Safety limits enforced on sends from this inbox: max_sends_per_hour, allowed_domains, blocked_domains, require_draft_approval, max_attachment_size_mb.\n",
        "tags": [
          "Guardrails"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current guardrails"
          }
        }
      },
      "put": {
        "summary": "Update inbox agent guardrails",
        "tags": [
          "Guardrails"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "max_sends_per_hour": {
                    "type": "integer"
                  },
                  "allowed_domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "blocked_domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "require_draft_approval": {
                    "type": "boolean"
                  },
                  "max_attachment_size_mb": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated guardrails"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/aliases": {
      "post": {
        "summary": "Add an alias address to an inbox",
        "description": "Route multiple addresses into one inbox.",
        "tags": [
          "Aliases"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "address"
                ],
                "properties": {
                  "address": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Alias created"
          }
        }
      },
      "get": {
        "summary": "List inbox aliases",
        "tags": [
          "Aliases"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of aliases"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/aliases/{alias_id}": {
      "delete": {
        "summary": "Delete an alias",
        "tags": [
          "Aliases"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "alias_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Alias deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/contacts": {
      "post": {
        "summary": "Add a contact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contact created"
          }
        }
      },
      "get": {
        "summary": "List contacts",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/contacts/{contact_id}": {
      "get": {
        "summary": "Get a contact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contact"
          }
        }
      },
      "delete": {
        "summary": "Delete a contact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Contact deleted"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/credentials": {
      "get": {
        "summary": "Get IMAP/SMTP credentials for an inbox",
        "description": "Raw mailbox credentials for connecting standard mail clients.",
        "tags": [
          "Inboxes"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "IMAP/SMTP host, port, username, password"
          }
        }
      }
    },
    "/v1/suppressions": {
      "post": {
        "summary": "Add a suppression",
        "description": "Prevent sending to an address (auto-populated from hard bounces).",
        "tags": [
          "Suppressions"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Suppression added"
          }
        }
      },
      "get": {
        "summary": "List suppressions",
        "tags": [
          "Suppressions"
        ],
        "responses": {
          "200": {
            "description": "List of suppressed addresses"
          }
        }
      }
    },
    "/v1/suppressions/{email}": {
      "delete": {
        "summary": "Remove a suppression",
        "tags": [
          "Suppressions"
        ],
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Suppression removed"
          }
        }
      }
    },
    "/v1/templates": {
      "post": {
        "summary": "Create an email template",
        "description": "Reusable templates with {{variable}} substitution referenced by template_id on send.",
        "tags": [
          "Templates"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "subject": {
                    "type": "string"
                  },
                  "text_body": {
                    "type": "string"
                  },
                  "html_body": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template created"
          }
        }
      },
      "get": {
        "summary": "List templates",
        "tags": [
          "Templates"
        ],
        "responses": {
          "200": {
            "description": "List of templates"
          }
        }
      }
    },
    "/v1/templates/{template_id}": {
      "get": {
        "summary": "Get a template",
        "tags": [
          "Templates"
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Template"
          }
        }
      },
      "put": {
        "summary": "Update a template",
        "tags": [
          "Templates"
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated template"
          }
        }
      },
      "delete": {
        "summary": "Delete a template",
        "tags": [
          "Templates"
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Template deleted"
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "summary": "List audit events",
        "description": "Agent-observability audit log of account activity.",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceHeader"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of events"
          }
        }
      }
    },
    "/v1/events/{event_id}": {
      "get": {
        "summary": "Get an audit event",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Event"
          }
        }
      }
    },
    "/v1/domains/search": {
      "get": {
        "summary": "Search domain availability",
        "tags": [
          "Domains"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability and pricing for the queried domain"
          }
        }
      }
    },
    "/v1/domains/search-bulk": {
      "post": {
        "summary": "Bulk domain availability search",
        "tags": [
          "Domains"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domains"
                ],
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Availability and pricing per domain"
          }
        }
      }
    },
    "/v1/domains/purchase": {
      "post": {
        "summary": "Purchase a domain",
        "description": "Register a domain (via the configured registrar) and attach it to the account.",
        "tags": [
          "Domains"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Domain purchased and registered"
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/stream": {
      "get": {
        "summary": "Stream inbound messages (Server-Sent Events)",
        "description": "A `text/event-stream` of new inbound messages for sandboxed agents that can't host a webhook. Authenticate via the `api_key` query parameter (EventSource cannot set headers). Each connection long-polls up to ~20s then closes; standard EventSource clients auto-reconnect and send `Last-Event-ID` to resume without missing messages. WebSockets remain the option for a single persistent connection.\n",
        "tags": [
          "Messages"
        ],
        "security": [],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "API key (dse_...) \u2014 EventSource cannot send an Authorization header."
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Resume cursor (received_at timestamp); usually supplied via Last-Event-ID."
          }
        ],
        "responses": {
          "200": {
            "description": "An event stream of message.received events",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/calendar/events": {
      "get": {
        "summary": "List calendar events across the account",
        "description": "Every event on every inbox the key can see, sorted by start_at. Same filters as the per-inbox listing plus an optional comma-separated `inbox_id` list. Scoped to the key's workspace when it has one. SDK: `calendar.list_all` / `calendar.listAll`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ISO 8601 date or datetime. Events starting at or after this."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ISO 8601 date or datetime. Events starting at or before this (a bare date means the end of that day)."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "confirmed",
                "tentative",
                "cancelled"
              ]
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "One or more inbox ids, comma-separated."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEventList"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/events": {
      "get": {
        "summary": "List an inbox's calendar events",
        "description": "Sorted by start_at. `from`/`to` bound the start time; `status` filters. Cursor pagination like the rest of the API. SDK: `calendar.list`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "confirmed",
                "tentative",
                "cancelled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEventList"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a calendar event",
        "description": "Puts an event on the inbox's calendar. Nothing is sent: call `invite` to send it to the attendees as a real invitation. The inbox is the organizer unless `organizer` says otherwise. Emits `calendar.event.created`. SDK: `calendar.create`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CalendarEventInput"
                  },
                  {
                    "required": [
                      "title",
                      "start"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The event.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEvent"
                }
              }
            }
          },
          "400": {
            "description": "Missing title or start, a naive time with no timezone, an unknown zone, end before start, or a duplicate ical_uid on this inbox."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/events/{event_id}": {
      "get": {
        "summary": "Get a calendar event",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The event.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEvent"
                }
              }
            }
          },
          "404": {
            "description": "No such event on this inbox."
          }
        }
      },
      "patch": {
        "summary": "Update a calendar event",
        "description": "Partial update; fields left out keep their values, and a moved `start` keeps the event's length unless `end` or `duration_minutes` is given. Once the event has been sent as an invitation, every update raises `sequence`, so the next `invite` goes out as a revision that calendar clients apply to the existing entry. Setting `status` to cancelled emits `calendar.event.cancelled`; anything else emits `calendar.event.updated`. SDK: `calendar.update`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalendarEventInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated event.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEvent"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a calendar event",
        "description": "Removes the row. Attendees are not told: to withdraw an invitation you sent, PATCH `status` to cancelled and call `invite` (which then sends a CANCEL) before deleting. Emits `calendar.event.cancelled` unless the event was already cancelled. SDK: `calendar.delete`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/events/{event_id}/invite": {
      "post": {
        "summary": "Send the event to its attendees as an invitation",
        "description": "Sends a real iCalendar invitation (METHOD:REQUEST) from the inbox to every attendee, through the normal send path (quota, guardrails and suppression apply; needs `messages.send`). The recipient sees Accept/Decline and the event lands on their calendar. The event keeps its `ical_uid`, so calling this again after a PATCH sends an update with a higher SEQUENCE that replaces the earlier entry rather than duplicating it. When the event's status is cancelled the message goes out as METHOD:CANCEL instead. Marks the event `source: sent` and links the message. The inbox must be the organizer. SDK: `calendar.invite`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "description": "Defaults to \"Invitation: {title}\", \"Updated invitation: {title}\" or \"Cancelled: {title}\"."
                  },
                  "text_body": {
                    "type": "string",
                    "description": "Covering text. Defaults to a line naming the event, when and where."
                  },
                  "html_body": {
                    "type": "string"
                  },
                  "attendees": {
                    "type": "array",
                    "description": "Replace the attendee list before sending.",
                    "items": {
                      "oneOf": [
                        {
                          "type": "string",
                          "format": "email"
                        },
                        {
                          "$ref": "#/components/schemas/CalendarAttendee"
                        }
                      ]
                    }
                  },
                  "in_reply_to": {
                    "type": "string",
                    "description": "A message_id to thread the invitation under."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarInviteResult"
                }
              }
            }
          },
          "400": {
            "description": "No attendees, or the inbox is not the event's organizer (answer with rsvp instead)."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/events/{event_id}/rsvp": {
      "post": {
        "summary": "Answer an invitation",
        "description": "Sends an iCalendar REPLY to the event's organizer with this inbox's PARTSTAT (through the normal send path; needs `messages.send`) and records the answer on the event's attendee entry. Only for events the inbox does not organize, which includes every invitation that arrived by email. Emits `calendar.event.updated`. SDK: `calendar.rsvp`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "response"
                ],
                "properties": {
                  "response": {
                    "type": "string",
                    "enum": [
                      "accepted",
                      "declined",
                      "tentative"
                    ]
                  },
                  "comment": {
                    "type": "string",
                    "description": "Sent as the body of the reply."
                  },
                  "subject": {
                    "type": "string",
                    "description": "Defaults to \"Accepted: {title}\" etc."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Replied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarRsvpResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid response, no organizer, or the inbox organizes this event itself."
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/feed": {
      "get": {
        "summary": "Get the inbox's calendar subscription URL",
        "description": "Returns the .ics feed URL (https and webcal) for this inbox, creating its feed token on first request. The same URL comes back on every call until it is rotated. Hand it to a human to add the agent's calendar to Google Calendar, Apple Calendar or Outlook. The token is the only credential on the feed, so treat the URL as a secret. SDK: `calendar.feed`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Feed URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarFeed"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar/feed/rotate": {
      "post": {
        "summary": "Rotate the calendar feed token",
        "description": "Issues a new feed token and invalidates the old URL immediately. Anyone subscribed to the old URL stops receiving updates. SDK: `calendar.rotate_feed` / `calendar.rotateFeed`.",
        "tags": [
          "Calendar"
        ],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "New feed URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarFeed"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{inbox_id}/calendar.ics": {
      "get": {
        "summary": "The calendar feed (iCalendar)",
        "description": "A `text/calendar` VCALENDAR of every non-cancelled event on the inbox, for calendar apps to subscribe to. Authenticated by the `token` query parameter alone (no API key), rate limited per IP. Times are UTC instants; `X-WR-TIMEZONE` carries the zone most events were given in.",
        "tags": [
          "Calendar"
        ],
        "security": [],
        "parameters": [
          {
            "name": "inbox_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "From GET /v1/inboxes/{inbox_id}/calendar/feed."
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token."
          }
        }
      }
    }
  }
}
