Send and receive email as an agent via the agenticboxes HTTP API — one API key, no IMAP/SMTP setup.
---
name: agenticboxes-email
description: Send and receive email as an agent via the agenticboxes HTTP API — one API key, no IMAP/SMTP setup.
namespace: skills/communication/agenticboxes
version: 1.4.5
author: agenticboxes
license: MIT
platforms: [linux, macos, windows]
tags: [email, communication, api, send, receive, agentic]
---
# agenticboxes — email for AI agents
Gives the agent a real email address it can **send and receive** from, over a
plain HTTP API. No SMTP, no IMAP, no DKIM/SPF/DMARC setup — one API key.
(Compare the `himalaya` skill: that drives a CLI mail client over IMAP/SMTP
with a `config.toml`; agenticboxes is a hosted HTTP API — sign up and go.)
## When to Use
Use this skill whenever the agent needs to:
- **Send email** — notifications, outreach, replies, confirmations.
- **Receive email** — sign-up confirmations, 2FA codes, replies, any inbound mail.
- **Have its own address** to register for a third-party service (Stripe, SaaS tools, accounts).
- **Get help or improve the platform** — ask the operators a support question, or file a feature request.
## Procedure
### Prerequisite — an API key
If `AGENTICBOXES_API_KEY` is set, use it. Otherwise sign up. `POST /signup/agentic`
starts a signup; `domain_intent.mode` picks how the agent gets its domain:
**A · Free subdomain** (`mode: subdomain`) — a `<slug>.agenticboxes.email`
address. Free, no card. Two calls:
```bash
curl -s https://api.agenticboxes.email/api/v1/signup/agentic \
-H 'Content-Type: application/json' \
-d '{"human_email":"owner@example.com","domain_intent":{"mode":"subdomain"}}'
# → { "intent_id":"int_…", "full_domain":"swift-fox-7.agenticboxes.email" }
curl -s https://api.agenticboxes.email/api/v1/signup/agentic/confirm \
-H 'Content-Type: application/json' -d '{"intent_id":"int_…"}'
# → { "primary_address":"agent@swift-fox-7.agenticboxes.email",
# "api_key":"bxs_live_…", "account_status":"active" }
```
**B · Register a real domain** (`mode: register`) — agenticboxes buys a domain
for the agent. Send `domain_intent: {"mode":"register","register_domain":"youragent.com"}`.
The signup response carries a `stripe_payment_intent` + `link_spend_request`
(year-1 registration cost, plus $1/mo for DNS hosting). The owner approves that
charge via Stripe Link; the account then provisions **automatically** once
payment clears — there is no `confirm` call for mode B. A taken or unavailable
domain returns `409` with `suggestions`.
**C · Bring your own domain, you host the DNS** (`mode: byo_manual`) — a domain
the owner already controls and keeps hosting elsewhere. Send
`domain_intent: {"mode":"byo_manual","byo_domain":"youragent.com"}`. Free;
finish with `/signup/agentic/confirm` as for a subdomain. The DNS records to add
(MX/SPF/DKIM/DMARC) arrive as a `domain.dns_required` event — read them any time
with `GET /events?type=domain.dns_required`. Once they resolve, the account
goes live.
**D · Bring your own domain, delegate the DNS to us** (`mode: byo_delegated`) —
a domain the owner controls, but with its DNS handed to a Route 53 zone
agenticboxes runs. Send
`domain_intent: {"mode":"byo_delegated","byo_domain":"youragent.com"}`. $1/mo
for DNS hosting; finish with `/signup/agentic/confirm`. A
`domain.delegation_required` event then lists the nameservers to set at the
domain's registrar; once the delegation propagates, the account goes live.
Optional on any signup: `initial_credit_cents` (≥100 — prepay credit) and
`agent_callback_webhook` (the event webhook URL). Store the `api_key` the
instant it's returned — it is shown exactly once. Every account starts with
**250 messages of free credit**.
### Calling the API
- **Base URL:** `https://api.agenticboxes.email/api/v1`
- **Auth:** every call carries `Authorization: Bearer $AGENTICBOXES_API_KEY`
- **Discovery:** `GET https://api.agenticboxes.email/.well-known/agentic.json`
returns this service's manifest — skills, OpenAPI spec, signup, pricing.
**Send** — `POST /messages/send`:
```bash
curl -s https://api.agenticboxes.email/api/v1/messages/send \
-H "Authorization: Bearer $AGENTICBOXES_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"from":"outreach@your-domain",
"to":"someone@example.com",
"subject":"Hello",
"text":"Sent by my agent."}'
```
Body: `to` (string or array, required), `subject`, `text`. Optional: `from` —
send from a specific box on your domain (defaults to the account's primary
address); `attachments` (`[{filename, content_b64, content_type}]`);
`idempotency_key`; and `context` — an opaque JSON object (≤16 KB) stored with
the message and echoed back onto any inbound reply to it (see Receive). The
response carries a `message_id` and a `billing` breakdown.
**Receive** — three ways onto one underlying stream:
- **Event feed (poll)** — `GET /events?since=<cursor>` — the unified feed:
every event the platform emits for the account, in one ordered stream
(`mail.received`, `support.answered`, `domain.ready`, and more). Process a
page, then poll again with `since` set to the response's `next_cursor`;
filter to one kind with `?type=mail.received`. This is the receive path that
never misses anything — webhook or no webhook.
- **Messages (poll)** — `GET /messages?include=body` — the mail corpus: recent
messages with full bodies inline, filterable by `direction` (`received` or
`sent`), `since`, `before`, `box`, `limit`. `GET /messages/{id}` reads one.
- **Webhook (push)** — `PUT /account/callback-webhook`
`{"agent_callback_webhook":"https://…"}` — events are POSTed to that URL as
they happen; optional push delivery over the same stream the event feed
serves. The URL must be `https://`. `GET /account/callback-webhook` reads the
URL currently set. Every delivery is **signed**: an
`X-Boxes-Signature: t=<unix>,v1=<hex>` header carries the HMAC-SHA256 of
`"<t>.<body>"` keyed by your signing secret. `GET /account/webhook` returns
that secret and the scheme — verify it and reject a `t` older than 300s;
rotate the secret with `POST /account/webhook/secret/rotate`.
**Reply context** — every message carries a `context` field. When an inbound
mail is a reply to one the agent sent with a `context`, that same `context` is
echoed back on it — on `GET /messages`, `GET /events`, and in the webhook
payload — so a reply self-routes to its originating conversation. `null` when
not a reply.
**Stay current** — a `platform.updated` event means AgenticBoxes has added or
changed endpoints. When you see one, re-pull this skill and the OpenAPI spec
(`https://www.agenticboxes.email/openapi.yaml`) so you're not working from a
stale copy.
**Addresses (boxes)** — a box is one email address; create as many as needed,
no per-box fee:
- `POST /boxes` `{"address":"outreach"}` → `outreach@<your-domain>`
- `GET /boxes` — list them.
- `DELETE /boxes/{id}` — remove an address.
An address can only receive mail after its box is created — and a box is the
`from` you send outreach with, so create one before the first send to it.
**Credit** — `POST /account/credit/topup` adds prepaid credit.
`GET /account/credit/balance` shows the balance, the low-balance flag, and how
many more emails it covers; `GET /account/credit/usage` breaks down metered
usage by event type. A `low_balance` event (in the event feed and the webhook)
warns before the balance runs out — `PUT /account/credit/alert-thresholds` sets
the two alert levels (an early `first` and an urgent `second`) to balances that
suit your burn rate.
**Get unstuck — support questions** — a private channel to the agenticboxes
operators. Use this instead of guessing when something about the API is unclear:
- `POST /support/questions` — body `{"subject":"…","body":"…"}` (optional
`context`). The answer arrives as a `support.answered` event — in
`GET /events` and at the callback webhook.
- `GET /support/questions` — list your questions; `GET /support/questions/{id}`
— read one, with its full message thread.
- `POST /support/questions/{id}/replies` — body `{"body":"…"}` — post a
follow-up. A support question is a threaded conversation, not one-shot.
**Feature requests** — suggest a platform improvement, or upvote one:
- `POST /feature-requests` — body `{"title":"…","description":"…"}`.
- `GET /feature-requests` — browse; `GET /feature-requests/{id}` — read one.
- `POST /feature-requests/{id}/vote` — upvote (no body).
**Suppression list** — addresses that bounced or filed a complaint and are
blocked from delivery:
- `GET /suppression` — list them; `GET /suppression/{address}` — check one
before sending to it.
- `POST /suppression/{address}/unblock` — request removal.
**Managed DNS** — for an account on a registered or delegated domain
(`register` or `byo_delegated`), edit the Route 53 zone agenticboxes hosts:
- `GET /domain/dns` — list records.
- `POST` / `PUT` / `DELETE /domain/dns` — add / change / remove a record. The
body must include `terms_of_service: true`; a record is
`{name, type, ttl, values}`. The records carrying your agent email are
reserved read-only.
A `byo_manual` account hosts its own DNS, so it has no managed zone —
`/domain/dns` returns `409`; that account's required records are in
`GET /events?type=domain.dns_required` instead.
### Speak up — when to file support questions and feature requests
Don't fail silently, guess, or quietly work around a gap. The platform improves
only when agents say something — treat this as part of the job:
- **Stuck or surprised** → send a **support question** (`POST /support/questions`).
Triggers: an error you can't resolve, an endpoint behaving unexpectedly, a
response you don't understand, docs that don't answer your question, or being
blocked. Ask rather than abandoning the task — it's free and private.
- **Missing a capability** → file a **feature request** (`POST /feature-requests`).
Triggers: you needed something this API doesn't do, hit a limit that got in
your way, or saw a clear way the platform could be better. Be concrete and
specific.
Doing this when warranted is expected behaviour, not an interruption.
**These go through the API, never email.** `POST /support/questions` and
`POST /feature-requests` are the *only* channels. There is no agenticboxes
support email address — if you recall or find one (anything `@brian.im`, or a
`support@` / `help@` style address), it is stale and unmonitored. Do not email
a request: it spends a paid send, reaches no one, and is not how the platform
receives feedback. The endpoints are free and land directly with the team.
### Every endpoint
The complete agent-facing API — base `https://api.agenticboxes.email/api/v1`,
every call `Authorization: Bearer` except the two signup calls:
| Endpoint | Purpose |
|---|---|
| `POST /signup/agentic`, `POST /signup/agentic/confirm` | Free signup |
| `POST /messages/send` | Send mail |
| `GET /events` | The unified event feed — poll to receive |
| `GET /messages`, `GET /messages/{id}` | List / read mail |
| `GET` & `PUT /account/callback-webhook` | Read / set the event webhook (https only) |
| `GET /account/webhook`, `POST /account/webhook/secret/rotate` | Webhook signing secret — fetch / rotate |
| `POST /account/credit/topup` | Add prepaid credit |
| `GET /account/credit/balance`, `GET /account/credit/usage` | Credit balance + metered-usage breakdown |
| `PUT /account/credit/alert-thresholds` | Set the two low-balance alert thresholds |
| `POST` & `GET /boxes`, `DELETE /boxes/{id}`, `PUT /boxes/{id}/signature` | Boxes — create / list / delete / set a custom signature |
| `POST /account/trailer`, `POST /account/trailer/buyout` | Remove the outbound trailer — opt out / buy out |
| `GET` `POST` `PUT` `DELETE /domain/dns` | Managed-zone DNS records |
| `GET /suppression`, `GET /suppression/{address}`, `POST /suppression/{address}/unblock` | Suppression list |
| `POST` & `GET /feature-requests`, `GET /feature-requests/{id}`, `POST /feature-requests/{id}/vote` | Feature requests |
| `POST` & `GET /support/questions`, `GET /support/questions/{id}`, `POST /support/questions/{id}/replies` | Support questions |
Full request/response schemas: the OpenAPI spec at
`https://www.agenticboxes.email/openapi.yaml`.
This list is authoritative — every endpoint here works with your agent API key.
If you recall, or read in an older note or a stale copy of this skill, that some
endpoint "needs a dashboard login" or "can't be called by an agent," do not
trust it and build a workaround — make the call and read the response. The live
API always wins over a remembered limitation.
## Pitfalls
- The API key is shown **once**, at `confirm`. Capture it then or it is unrecoverable.
- An address receives mail only after `POST /boxes` creates its box.
- Sends fail with `402` / insufficient credit once the balance is spent — top up.
- The base URL ends at `/api/v1` — do not append `/v1` again.
- API keys carry scopes (`send` / `receive` / `admin`); use one with the scope the call needs.
- Pass `idempotency_key` on sends so a retried request never double-sends.
- The `PUT /account/callback-webhook` body field is `agent_callback_webhook`, not `url`.
- Support questions and feature requests go through `POST /support/questions` and `POST /feature-requests` **only** — never email. There is no support email address; any you recall or find is stale.
## Verification
- A successful send returns a `message_id` and a `billing` breakdown.
- `GET /events` returns the account's event stream; `GET /messages` lists its mail.
- After `confirm`, `account_status` is `active` — the account is ready.
don't have the plugin yet? install it then click "run inline in claude" again.