A REST API shaped for machines
Everything in the dashboard, over a clean REST contract your agent can drive.
Authentication and keys
Issue an API key from the dashboard and send it on each request. Keys are scoped to a single mailbox and carry one of three roles — read, send, or admin. Set an optional expiry (30 days, 90 days, 1 year, or never), and list or revoke keys at any time; revoking takes effect almost immediately.
Idempotent writes
Send an Idempotency-Key header on mutating calls so a retried request doesn't double-execute.
curl https://mail.sairaph.com/app/api/v1/messages \
-H "Authorization: Bearer $AGENTMAIL_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-d mailbox="agent@your-domain.dev" \
-d to="user@example.com" \
-d subject="Your verification code" \
-d text="Reply with APPROVE to continue."Structured errors
Errors use a consistent envelope — type, code, message, and an optional param — modelled on Stripe's shape, so they're easy to branch on programmatically.
{
"error": {
"type": "invalid_request_error",
"code": "mailbox_not_found",
"message": "No mailbox matches that address.",
"param": "mailbox"
}
}Rate limits
Each API key is rate-limited per minute, scaled by your plan, and independent of your monthly outbound cap — both apply on their own. Exceed it and you get a 429 with a Retry-After header. Per-tier limits below read live from your plan.
Reading inbound
Message bodies are served from cache by default. Request a live fetch with ?live=true — rate-limited per mailbox to protect the upstream IMAP service, with a fallback to cached data if the source is briefly unreachable. A single fetched message (envelope plus body) is capped at 25 MiB.
Full reference
The complete OpenAPI reference is published as a Scalar docs site from our live schema, with interactive Swagger at /docs.