
Dead Simple Email · io.pilot.deadsimple
Dead Simple Email
An email identity your agent provisions for itself, then uses to send, receive, and read its own signup codes. See setup and usage details.
Communications · Live on the catalogue
$ pilotctl appstore install io.pilot.deadsimple- Version
- v0.1.0
- Methods
- 19
- Size
- —
- Permissions
- 4 declared
- Platforms
- macOS · Linux
About Dead Simple Email
Dead Simple Email gives an agent a real, deliverable email identity — not a sandbox — and it can get one entirely on its own. A single call to deadsimple.signup returns an account, an API key and a live inbox. No dashboard, no verification email, no human in the loop.
The method agents reach for most is deadsimple.get_verification_code. It pulls the one-time code or magic link straight out of the newest inbound message, so an agent can sign itself up for a third-party service or clear a 2FA prompt without ever parsing an email body. Filter by sender and by timestamp so a stale code is never returned. This is what turns "the provider emails you a code" from a dead end into a step.
From there the agent sends, replies on-thread, reply-alls, forwards, reads full messages with headers and attachments, and walks whole conversation threads over one REST API.
Underneath is real sending infrastructure: DKIM-signed egress through a dedicated MTA, bounce and complaint handling, suppression lists, and optional open and click tracking. Inbound mail can be pushed to HMAC-SHA256 signed webhooks that retry on exponential backoff. A supervisor agent can watch every inbox in a workspace at once with list_all_messages, and inboxes can be created in bulk, tagged, and torn down when a throwaway identity is finished.
Tiers. A self-provisioned agent account starts on trial: 1 inbox, 10 sends an hour, 25 a day. Calling deadsimple.claim with an email a human controls, then deadsimple.claim_verify, moves it to the Free plan — 5 inboxes and 5,000 emails a month — keeping the same API key, inboxes and history. Paid plans scale to 500 inboxes, 25 custom domains, and 1,000 requests a minute.
Edge cases. A 429 with code trial_send_limit_exceeded is a quota signal, not a transient failure — do not blindly retry, claim the account instead. Pagination is cursor-based. Spam is excluded from list_messages unless include_spam is true. Delete throwaway inboxes when finished so they stop counting against the quota.
Methods · 19
deadsimple.signupSTART HERE if you have no key. Provisions a Dead Simple account, an API key and a live inbox in one call, with no human, no dashboard and no verification email. Returns {account_id, api_key, inbox}. Save api_key as the DEADSIMPLE_API_KEY secret — every other method authenticates with it. Idempotent per Idempotency-Key, so a retry after a dropped connection returns the same account rather than a second one. The account starts on the trial tier: 1 inbox, 10 sends an hour, 25 a day.deadsimple.claimStart lifting the trial caps by attaching an email address a human controls. Sends a 6-digit code to that address; pass it to deadsimple.claim_verify to finish. Your existing API key, inboxes and message history are untouched by the upgrade.deadsimple.claim_verifyConfirm the code from deadsimple.claim and move the account from trial to the Free plan (5 inboxes, 5,000 emails a month). The same API key keeps working.deadsimple.create_inboxCreate a real, deliverable email inbox in one call. Returns an inbox_id and a live address that can send and receive immediately — no SMTP setup, no DNS, no mailbox provisioning. Use this when you already have a key and want an additional identity.deadsimple.list_inboxesList the inboxes this key can see, newest first. Cursor-paginated: pass the cursor from the previous response for the next page.deadsimple.get_inboxFetch one inbox: its address, display name, tags, status, and counters.deadsimple.delete_inboxPermanently delete an inbox and its stored messages. IRREVERSIBLE. Use when a throwaway identity is finished so it stops counting against the inbox quota.deadsimple.send_emailSend an email from one of your inboxes. Plain text or HTML, cc/bcc, base64 attachments, scheduled send, and optional open/click tracking. Real DKIM-signed egress, not a test harness. On the trial tier this is capped at 10 an hour and 25 a day; a 429 with code trial_send_limit_exceeded is a quota signal, not a transient failure.deadsimple.get_verification_codeTHE method agents reach for. Pulls the one-time code or magic link straight out of the newest inbound message, so a signup or 2FA prompt can be cleared without parsing an email body. Non-blocking: returns found=false if nothing has arrived, so poll every 2-3 seconds for up to a minute after triggering the mail. Set `since` to a timestamp taken BEFORE you triggered it, and `from_contains` to the sender domain, so a stale code is never returned.deadsimple.list_messagesList messages in an inbox, newest first, with sender, subject, snippet, and labels. Spam is excluded unless include_spam is true. Cursor-paginated.deadsimple.get_messageGet one message in full: headers, plain-text and HTML bodies, and attachment metadata.deadsimple.replyReply to the sender of a message. Threading headers are set automatically so the reply lands in the same conversation — never hand-build In-Reply-To.deadsimple.reply_allReply to the sender and every other recipient of a message, with threading headers set automatically.deadsimple.forwardForward a message, with its attachments, to new recipients.deadsimple.list_threadsList conversation threads in an inbox, each with its latest message, so an agent can track ongoing exchanges instead of loose messages.deadsimple.get_threadGet a full conversation thread with every message in order — the context an agent needs before replying.deadsimple.get_attachmentGet a time-limited signed download URL for an attachment. The link expires in one hour.deadsimple.list_all_messagesList messages across every inbox this key can see, newest first. For a supervisor agent watching many identities at once — cheaper than iterating inboxes.deadsimple.create_webhookRegister an HMAC-SHA256 signed webhook for inbound mail, bounces, and complaints, so long-running work does not have to poll list_messages in a loop. Deliveries retry on exponential backoff and every attempt is logged.Full usage demo
When your agent needs an email address of its own: to sign itself up for a third-party service and read the code back, or to send and receive real mail as part of a task.
Run this first — Get an account, an API key and a live inbox in one callCallpilotctl appstore call io.pilot.deadsimple deadsimple.signup '{"label":"my-agent"}'→{"data":{"account_id":"...","api_key":"dse_...","inbox":{"inbox_id":"...","email":"...@box1.deadsimple.email"},"plan":{"plan":"trial","inbox_limit":1,"sends_per_hour":10}}}Everything is under data. Save data.api_key as DEADSIMPLE_API_KEY — it is shown once. Already have a key? Skip this and call create_inbox.
Worked examples
Sign up for a third-party service and read the code backCallpilotctl appstore call io.pilot.deadsimple deadsimple.get_verification_code '{"inbox_id":"<id>","since":"2026-08-06T12:00:00Z","from_contains":"stripe.com"}'→{"data":{"found":true,"code":"481920","magic_link":null,"message_id":"..."}}Note the time BEFORE submitting your address, pass it as `since`, then poll every 2-3s. found=false just means it has not landed yet. Never parse the raw email yourself.
Send a real emailCallpilotctl appstore call io.pilot.deadsimple deadsimple.send_email '{"inbox_id":"<id>","to":"someone@example.com","subject":"Report ready","text_body":"The run finished."}'→{"data":{"message_id":"...","status":"queued"}}DKIM-signed egress, not a sandbox. Trial caps this at 10/hour, 25/day.
Read a conversation before replyingCallpilotctl appstore call io.pilot.deadsimple deadsimple.get_thread '{"inbox_id":"<id>","thread_id":"<tid>"}'→{"data":{"thread_id":"...","messages":[{"message_id":"...","from":"...","subject":"..."}]}}Then reply with the message_id; threading headers are set for you.
Good to know
- Every response is wrapped: the payload is under data, with meta.request_id beside it.
- Call signup only when you have no key. It is idempotent per Idempotency-Key, so a retry returns the same account, not a second one.
- Trial is 1 inbox, 10 sends/hour, 25/day. A 429 trial_send_limit_exceeded is a QUOTA signal, not transient — do not retry it.
- Lift the caps with claim then claim_verify. Your key, inboxes and history survive.
- get_verification_code needs since from BEFORE you triggered the mail, or you may read a stale code.
Next
io.pilot.deadsimple deadsimple.help '{}'
What’s New
v0.1.0Latest—- First release on the Pilot app store.