Machine Readiness
Stored receipt and evidence
46
45
50
0
100
Samples
No stored offer samples.
Samples
Send an email from "StableEmail" <relay@stableemail.dev> ($0.02)
https://stableemail.dev/api/sendPurchase a custom email subdomain on stableemail.dev ($5)
https://stableemail.dev/api/subdomain/buySend email from your custom subdomain on stableemail.dev ($0.005)
https://stableemail.dev/api/subdomain/sendSamples
No stored product samples.
Document
Not stored for this site.
Document
# StableEmail — Pay-per-send email via micropayments
> Send email with a single HTTP request. No API keys. No accounts. Pay $0.02 per email.
## Base URL
https://stableemail.dev
## Discovery
GET /.well-known/x402
## Endpoints
### POST /api/send — Send email (shared domain)
- Protection: x402/MPP payment ($0.02 USDC on Base, Solana, or Tempo)
- Sends from: relay@stableemail.dev
- Body: { "to": ["email"], "subject": "string", "html": "string", "text": "string", "replyTo": "email", "attachments": [{"content": "base64...", "contentType": "application/pdf", "filename": "file.pdf"}] }
- Requires either "html" or "text" (or both)
- "attachments" is optional, max 5, each with base64 content (~3.75MB decoded limit), MIME contentType, and filename
- For calendar invites (.ics), use contentType: "text/calendar; method=REQUEST"
- Returns: { "success": true, "messageId": "string", "from": "string" }
### POST /api/subdomain/buy — Purchase a custom subdomain
- Protection: x402/MPP payment ($5 USDC)
- Body: { "subdomain": "yourname" }
- Subdomain rules: 3-30 chars, lowercase alphanumeric + hyphens
- Creates yourname.stableemail.dev with full email sending capability
- DNS verification takes ~5 minutes after purchase
- Returns: { "success": true, "subdomain": "yourname.stableemail.dev", "dnsStatus": "pending" }
### POST /api/subdomain/send — Send from custom subdomain
- Protection: x402/MPP payment ($0.005 USDC)
- Payer wallet must be owner or authorized signer for the subdomain
- Body: { "from": "you@yourname.stableemail.dev", "to": ["email"], "subject": "string", "html": "string", "text": "string", "replyTo": "email" }
- Returns: { "success": true, "messageId": "string", "from": "string" }
### POST /api/subdomain/signers — Manage authorized wallets
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can manage signers
- Body: { "action": "add" | "remove", "subdomain": "yourname", "walletAddress": "0x..." }
- Max 50 signers per subdomain
### POST /api/subdomain/update — Update subdomain settings
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can update
- Body: { "subdomain": "yourname", "catchAllForwardTo": "catch-all@example.com" }
- Set catchAllForwardTo to null to remove catch-all forwarding
- Catch-all forwards emails to unmatched addresses on the subdomain
### GET /api/subdomain/status?subdomain=yourname — Check subdomain status
- Protection: SIWX wallet proof only (free, no payment)
- Owner or any signer can check status
- Returns: { "subdomain": "string", "ownerWallet": "string", "dnsVerified": bool, "sesVerified": bool, "signerCount": number, "signers": ["0x..."] }
## Subdomain Inboxes — Receive Email on Subdomains
Subdomain owners can create per-address inboxes on their subdomain (e.g., `biden@craig.stableemail.dev`). $0.25 to create (x402/MPP payment), cap 100 per subdomain. Each inbox optionally forwards to a real address and/or retains messages for programmatic API access. Unmatched addresses go to the subdomain's catch-all forwarder if set, otherwise silently dropped.
### POST /api/subdomain/inbox/create — Create inbox on subdomain ($0.25)
- Protection: x402/MPP payment ($0.25 USDC on Base, Solana, or Tempo)
- Payer wallet must be the subdomain owner
- Body: { "subdomain": "craig", "localPart": "biden", "forwardTo": "joe@gmail.com" }
- forwardTo is optional — omit for programmatic-only mailbox (retainMessages auto-enabled)
- Max 100 inboxes per subdomain, 500 messages per inbox
- Returns: { "success": true, "inbox": "biden@craig.stableemail.dev", "retainMessages": true, "messageLimit": 500 }
### POST /api/subdomain/inbox/list — List subdomain inboxes
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can list
- Body: { "subdomain": "craig" }
- Returns: { "success": true, "inboxes": [{ "localPart": "string", "address": "string", "forwardTo": "string?", "retainMessages": bool, "active": bool, "messageCount": number, "unreadCount": number }] }
### POST /api/subdomain/inbox/update — Update inbox settings
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can update
- Body: { "subdomain": "craig", "localPart": "biden", "forwardTo": "newemail@example.com", "retainMessages": true }
- At least one of "forwardTo" or "retainMessages" is required
- Set forwardTo to null to remove forwarding
- Returns: { "success": true, "inbox": "biden@craig.stableemail.dev", "forwardTo": "string?", "retainMessages": bool }
### POST /api/subdomain/inbox/delete — Delete inbox from subdomain
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can delete
- Body: { "subdomain": "craig", "localPart": "biden" }
- Cascades: deletes all messages from DB and S3
- Returns: { "success": true, "deleted": "biden@craig.stableemail.dev", "messagesDeleted": number }
### POST /api/subdomain/inbox/messages — List inbox messages
- Protection: x402/MPP payment ($0.001 USDC on Base, Solana, or Tempo)
- Payer wallet must be the subdomain owner
- Body: { "subdomain": "craig", "localPart": "biden", "cursor": "message id (optional)", "limit": 20 }
- Returns: { "success": true, "messages": [...], "nextCursor": "string?", "messageCount": number, "messageLimit": 500, "warning": "string?" }
- Warning field appears when inbox is at or near capacity (>=80%). Delete old messages to free space.
### POST /api/subdomain/inbox/messages/read — Read a single message
- Protection: x402/MPP payment ($0.001 USDC on Base, Solana, or Tempo)
- Payer wallet must be the subdomain owner
- Body: { "messageId": "string" }
- Returns: { "success": true, "message": { "id": "string", "from": "string", "to": ["string"], "subject": "string", "date": "ISO date", "text": "string", "html": "string", "attachments": [{ "filename": "string", "contentType": "string", "size": number }], "receivedAt": "ISO date" } }
- Marks the message as read
### POST /api/subdomain/inbox/messages/delete — Delete a message
- Protection: SIWX wallet proof only (free, no payment)
- Only the subdomain owner can delete messages
- Body: { "messageId": "string" }
- Returns: { "success": true, "deleted": "string" }
## Forwarding Inbox
Buy `username@stableemail.dev` for $1/month. Use it as a forwarding inbox (emails forwarded to your real address), a programmatic mailbox (read messages via API), or both. You can also send from your inbox address. Duration-based pricing with bulk discounts. Anyone can top up any inbox. Cancel anytime for a pro-rata refund.
### POST /api/inbox/buy — Buy an inbox ($1, 30 days)
- Protection: x402/MPP payment ($1 USDC on Base, Solana, or Tempo)
- Body: { "username": "alice", "forwardTo": "alice@gmail.com" }
- forwardTo is optional — omit it to use as a programmatic mailbox (retainMessages enabled automatically, read messages via /api/inbox/messages)
- Username rules: 3-30 chars, lowercase alphanumeric + hyphens
- Subdomain owners can buy the matching inbox name (e.g., owner of alice.stableemail.dev can buy alice@stableemail.dev)
- Returns: { "success": true, "inbox": "alice@stableemail.dev", "retainMessages": true, "expiresAt": "ISO date", "daysRemaining": 30 }
### POST /api/inbox/topup — Top up inbox 30 days ($1)
- Protection: x402/MPP payment ($1 USDC)
- Anyone can top up any inbox — no SIWX required
- Body: { "username": "alice" }
- Returns: { "success": true, "inbox": "alice", "expiresAt": "ISO date", "daysRemaining": number, "daysAdded": 30 }
### POST /api/inbox/topup/quarter — Top up inbox 90 days ($2.50, save 17%)
- Protection: x402/MPP payment ($2.50 USDC)
- Anyone can top up any inbox — no SIWX required
- Body: { "username": "alice" }
- Returns: { "success": true, "inbox": "alice", "expiresAt": "ISO date", "daysRemaining": number, "daysAdded": 90 }
### POST /api/inbox/topup/year — Top up inbox 365 days ($8, save 34%)
- Protection: x402/MPP payment ($8 USDC)
- Anyone can top up any inbox — no SIWX required
- Body: { "username": "alice" }
- Returns: { "success": true, "inbox": "alice", "expiresAt": "ISO date", "daysRemaining": number, "daysAdded": 365 }
### POST /api/inbox/send — Send from your inbox address ($0.005)
- Protection: x402/MPP payment ($0.005 USDC)
- Payer wallet must be the inbox owner
- Body: { "username": "alice", "to": ["bob@example.com"], "subject": "Hello", "html": "<p>Hi</p>", "text": "Hi", "replyTo": "alice@gmail.com" }
- Requires either "html" or "text" (or both)
- Returns: { "success": true, "messageId": "string", "from": "alice@stableemail.dev" }
### GET /api/inbox/status?username=alice — Check inbox status
- Protection: SIWX wallet proof only (free, no payment)
- Only the inbox owner can check status
- Returns: { "inbox": "alice@stableemail.dev", "ownerWallet": "0x...", "forwardTo": "email", "retainMessages": bool, "expiresAt": "ISO date", "daysRemaining": number, "daysOwned": number, "active": bool, "pricing": {...} }
### POST /api/inbox/update — Update inbox settings
- Protection: SIWX wallet proof only (free, no payment)
- Only the inbox owner can update
- Body: { "username": "alice", "forwardTo": "newemail@example.com", "retainMessages": true }
- At least one of "forwardTo" or "retainMessages" is required
- "retainMessages": when true, inbound emails are kept in S3 for programmatic access via the messages API
- Returns: { "success": true, "inbox": "alice@stableemail.dev", "forwardTo": "newemail@example.com", "retainMessages": true }
### POST /api/inbox/cancel — Cancel inbox and get pro-rata USDC refund
- Protection: SIWX wallet proof only (free, no payment)
- Only the inbox owner can cancel
- Body: { "username": "alice" }
- Refund is sent on-chain to the caller's wallet automatically
- Refunds below $0.01 are waived (too small to transfer)
- Returns: { "success": true, "inbox": "alice@stableemail.dev", "cancelled": true, "refund": { "amount": "0.50", "currency": "USDC", "network": "eip155:8453", "to": "0x...", "status": "completed", "transactionHash": "0x..." }, "daysRemaining": 15 }
## Inbox Messages API
Read inbound emails programmatically. Requires "retainMessages": true on the inbox (set via POST /api/inbox/update).
### POST /api/inbox/messages — List messages
- Protection: x402/MPP payment ($0.001 USDC on Base, Solana, or Tempo)
- Payer wallet must be the inbox owner
- Body: { "username": "alice", "cursor": "message id (optional)", "limit": 20 }
- Returns: { "success": true, "messages": [{ "id": "string", "fromEmail": "string", "subject": "string", "receivedAt": "ISO date", "read": bool }], "nextCursor": "message id (optional)" }
- Paginated: pass "nextCursor" as "cursor" in the next request
### POST /api/inbox/messages/read — Read a single message
- Protection: x402/MPP payment ($0.001 USDC on Base, Solana, or Tempo)
- Payer wallet must be the inbox owner
- Body: { "messageId": "string" }
- Returns: { "success": true, "message": { "id": "string", "from": "string", "to": ["string"], "subject": "string", "date": "ISO date", "text": "string", "html": "string", "attachments": [{ "filename": "string", "contentType": "string", "size": number }], "receivedAt": "ISO date" } }
- Marks the message as read
### POST /api/inbox/messages/delete — Delete a message
- Protection: SIWX wallet proof only (free, no payment)
- Only the inbox owner can delete messages
- Body: { "messageId": "string" }
- Removes the message from DB and S3 storage
- Returns: { "success": true, "deleted": "string" }
## Images in Emails
To include images, use `<img src="url">` in the "html" body. Host images on stableupload.dev (x402/MPP-powered file uploads, see https://stableupload.dev/llms.txt). Upload via x402/MPP payment → get a public URL → reference in HTML. Prefer hosted URLs over base64 data URIs — most email clients strip data URIs.
## Agent Integration
The recommended way for AI agents to interact with StableEmail is via [agentcash-skills](https://github.com/Merit-Systems/agentcash-skills) — available as an MCP server (`npx -y agentcash@latest`) or CLI (`npx agentcash fetch ...`). It handles payment negotiation and retry logic automatically. Any x402/MPP-compatible client paying USDC on Base, Solana, or Tempo will also work.
## Payment Details
- Network: Base (eip155:8453), Solana, or Tempo
- Currency: USDC
- Protocol: x402 (https://www.x402.org) / MPP (https://mpp.dev)
- Send first request → receive 402 with PAYMENT-REQUIRED header → sign payment → resend with payment header
## SIWX Authentication
Free management endpoints (status, update, cancel, signers) use SIWX for wallet identity verification. These endpoints return a 402 with SIWX challenge in the PAYMENT-REQUIRED header (same flow as x402/MPP payment). x402/MPP-compatible clients (like agentcash) handle this automatically — no special handling needed.
Paid send endpoints identify the wallet from the x402/MPP payment header instead.
SIWX is part of the x402/MPP protocol extensions (CAIP-122 compliant, supports EVM + Solana).
Document
Not stored for this site.