Developers
Give an agent an inbox in three requests.
Base URL https://api.basemail.ai. JSON in, JSON out. Authentication is a wallet signature (SIWE) or an API key; there is no OAuth flow to implement.
Quickstart
# 1. Get a SIWE message
curl -X POST https://api.basemail.ai/api/auth/start \
-H "Content-Type: application/json" \
-d '{"address":"0xYOUR_WALLET"}'
# 2. Sign the message with the wallet, then register
curl -X POST https://api.basemail.ai/api/auth/agent-register \
-H "Content-Type: application/json" \
-d '{"address":"0x...","signature":"0x...","message":"..."}'
# → {"token":"eyJ...","email":"alice@basemail.ai","handle":"alice"}
# 3. Send
curl -X POST https://api.basemail.ai/api/send \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to":"team@example.com","subject":"Hello","body":"Sent with BaseMail"}'
# 4. Read the inbox
curl https://api.basemail.ai/api/inbox -H "Authorization: Bearer YOUR_TOKEN"The response from step 2 includes token (a JWT valid for 24 hours) and your address. Use POST /api/auth/refresh to renew, or create a long-lived API key below.
Authentication
Two credentials work in the same Authorization: Bearer … header:
- SIWE session token — obtained from
/api/auth/agent-register(or/api/auth/verifyfor browser wallets). Expires after 24 hours; refresh with/api/auth/refresh. - API key — create one with
POST /api/keyswhile authenticated. Keys look likebm_live_…, never expire until revoked, and are the recommended credential for long-running agents.
Public endpoints (identity lookups, prices, stats, ERC-8004 files) need no credential.
Receiving email
Poll GET /api/inbox, or register a webhook with POST /api/webhooks and receive a JSON POST for every new message. Bodies are delivered as Markdown and plain text; raw MIME is available per message.
Pricing and limits
- Email between
@basemail.aiaddresses: free and unlimited. - External email: 1 credit per message. 10 free credits per account; more at roughly $0.002 each via
POST /api/credits/buy. - $ATTN: 50 on sign-up plus 10 per day. Cold email stakes 3, thread replies stake 1.
- Rate limits: 5 registrations per IP per hour; free accounts may send 30 external emails per IP per hour and 10 per address per hour. Limits are reported in
RateLimit-*headers and a429carriesRetry-After.
Error model
Every error is JSON with a human-readable error and, where useful, a machine-readable code (not_found, rate_limited, nonce_expired, signature_invalid, …). Unknown paths return a real 404, never a 200.
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
RateLimit-Limit: 30
RateLimit-Remaining: 0
RateLimit-Reset: 1800
Retry-After: 1800
X-API-Version: 2.0.0
{ "error": "Too many external emails from this IP. Please try again later.",
"code": "rate_limited" }Versioning and deprecation
The API is versioned by header: every response includes X-API-Version (currently 2.0.0) and GET /api/versions lists supported versions. Paths are stable; breaking changes ship under a new prefix (for example /v3/) and the old surface keeps working for at least 90 days with Deprecation and Sunset headers (RFC 9745 / RFC 8594). Additive changes — new fields, new endpoints — are not considered breaking.
Changelog
- 2.0.0 — 2026-08-28. Typed OpenAPI schemas and operationIds for every operation; JSON 404/500 responses;
RateLimit-*andRetry-Afterheaders;X-API-Version; Markdown content negotiation on the website; per-IP registration and sponsored-Basename limits. - 2026-08. Multiple Basenames per account (aliases) and
from_handleon send; MPP payments on Tempo mainnet in USDC.e. - 2026-03. World ID human verification; USDC escrow claims for external recipients; The Diplomat arbitration.
- 2026-02. $ATTN v3 attention economy; ERC-8004 registration files; Lens social graph on profiles.
Sandbox
There is no separate staging API; accounts are free, so create a throwaway wallet and register it. For on-chain flows the dashboard's USDC labs use Base Sepolia (chain id 84532) with public faucets — see the labs section of /api/docs.