PlatformReference
Run a mailbox through the API
Turn on API access for one mailbox, then read, send and file its mail from your own code with a key that reaches that mailbox and nothing else.
A mailbox can be run from your own code: a support bot that answers support@, a script that files invoices, a service that sends from sales@. You turn on API access for that one mailbox and get a key. The key reaches that mailbox only. It can't read your other mailboxes, change the mailbox's settings, or make more keys.
Turn on API access
- Open the mailbox, then Settings → API.
- Name the key after what will use it, choose what it may do, and choose when it expires.
- Select Turn on API access. The key appears once. Copy it now: only its last four characters are kept afterwards.
Each mailbox can have up to 20 keys. API access is on while a mailbox has a key. Turn off API access revokes every key; revoking one key stops only that one. A revoked key stops working within a minute.
| Access | What the key may do |
|---|---|
| Full access | Read, send, file and organize mail; folders, rules and contacts |
| Send only | Send mail and upload the files it carries; read which addresses it may send as |
| Read only | Read mail, threads, counts, folders, rules and contacts |
No key can reach the mailbox's settings, signatures, aliases, the assistant, AI summaries, or other mailboxes.
Authenticate
Send the key as a bearer token. The base address is https://api.contextstream.io,
and every route below begins with /api/v1/mail.
curl https://api.contextstream.io/api/v1/mail/key \
-H "Authorization: Bearer $CONTEXTMAIL_KEY"{ "success": true, "data": { "address": "[email protected]", "access": "full", "name": "Support bot", "key_id": "…" } }Every answer is wrapped the same way: success, then data or error.
Send a message
curl https://api.contextstream.io/api/v1/mail/accounts/[email protected]/send \
-H "Authorization: Bearer $CONTEXTMAIL_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": [{ "email": "[email protected]", "name": "Ana" }],
"subject": "Your ticket",
"text": "We found the problem and fixed it.",
"html": "<p>We found the problem and fixed it.</p>"
}'| Field | |
|---|---|
to, cc, bcc | Lists of { "email", "name" }. to is required. |
subject, text | The text part always goes, even with html. |
html | Optional. Cleaned before it leaves: text formatting, links, lists, quotes and code stay; scripts, images and other styles are removed. |
identity_id | Send as another of the mailbox's addresses (from GET …/identities). |
reply_to_id | A message id: the new message is a reply in its thread. |
forward_of_id | A message id to forward. |
attachments | Ids of uploaded files (next section). |
The mailbox's signature is added, as it is when you send from the app.
Attach files
A file is uploaded straight to storage first, then named when you send.
# 1. Ask for a place to put it.
curl https://api.contextstream.io/api/v1/mail/accounts/[email protected]/attachments \
-H "Authorization: Bearer $CONTEXTMAIL_KEY" -H "Content-Type: application/json" \
-d '{ "name": "report.pdf", "type": "application/pdf", "size": 482113 }'
# 2. PUT the file to the upload_url it returns, with its upload_headers.
curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @report.pdf
# 3. Send with "attachments": ["<the id from step 1>"].Files can be up to 300 MB. The smallest are attached while the message stays
under 18 MB; the rest go as download links that work for 90 days. size
must be the file's exact size in bytes.
Read mail
| Route | |
|---|---|
GET /accounts/{address}/messages | A page of messages. folder (inbox by default, or a folder id), limit, position, sort (newest or oldest), q to search. |
GET /accounts/{address}/messages/{id} | One message with its text and HTML. |
GET /accounts/{address}/messages/{id}/thread | Its whole conversation. |
GET /accounts/{address}/counts | How many messages a folder holds (folder, the Inbox by default), and how many are flagged, prioritized or in each triage category. |
GET /accounts/{address}/folders | The mailbox's folders, with their ids. |
GET /accounts/{address}/identities | The addresses it can send as. |
curl "https://api.contextstream.io/api/v1/mail/accounts/[email protected]/messages?folder=inbox&limit=25" \
-H "Authorization: Bearer $CONTEXTMAIL_KEY"New mail
There are no webhooks for incoming mail yet. To pick up new mail, list the Inbox newest first every minute or so and act on what you haven't seen. When you have handled a message, mark it read or move it out of the Inbox, so the next look only finds what is new.
File and organize
POST /accounts/{address}/messages/{id}/actions with an action:
action | |
|---|---|
seen, unseen | Mark read or unread. |
flag, unflag | Flag. |
archive, trash, restore | Archive, move to Trash, bring back from Trash. |
move | Into folder_id. |
spam, ignore | Mark as spam, or file into Ignore. |
priority | Set level: high, medium, low or none. |
curl https://api.contextstream.io/api/v1/mail/accounts/[email protected]/messages/$ID/actions \
-H "Authorization: Bearer $CONTEXTMAIL_KEY" -H "Content-Type: application/json" \
-d '{ "action": "archive" }'With full access a key can also make and remove folders (POST …/folders,
PATCH or DELETE …/folders/{id}), sender rules (GET or POST …/rules,
DELETE …/rules/{id}) and contacts (…/contacts), save drafts
(POST …/drafts) and empty Trash (POST …/trash/empty).
If it doesn't work
- 401 Unauthorized. The key is wrong, revoked or expired, or the mailbox was removed. Make a new key in Settings → API.
- 403 "This key is for … only". The address in the path isn't the key's mailbox. A key reaches one mailbox; make a key in the other mailbox's settings.
- 403 "A send key can't call this route" (or read, or "a mailbox API key can't call this route"). The route needs more access than the key has, or no key may call it. Make a key with the access the job needs.