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

  1. Open the mailbox, then Settings → API.
  2. Name the key after what will use it, choose what it may do, and choose when it expires.
  3. 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.

AccessWhat the key may do
Full accessRead, send, file and organize mail; folders, rules and contacts
Send onlySend mail and upload the files it carries; read which addresses it may send as
Read onlyRead 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.

Terminal
curl https://api.contextstream.io/api/v1/mail/key \
  -H "Authorization: Bearer $CONTEXTMAIL_KEY"
JSON
{ "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

Terminal
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, bccLists of { "email", "name" }. to is required.
subject, textThe text part always goes, even with html.
htmlOptional. Cleaned before it leaves: text formatting, links, lists, quotes and code stay; scripts, images and other styles are removed.
identity_idSend as another of the mailbox's addresses (from GET …/identities).
reply_to_idA message id: the new message is a reply in its thread.
forward_of_idA message id to forward.
attachmentsIds 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.

Terminal
# 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}/messagesA 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}/threadIts whole conversation.
GET /accounts/{address}/countsHow many messages a folder holds (folder, the Inbox by default), and how many are flagged, prioritized or in each triage category.
GET /accounts/{address}/foldersThe mailbox's folders, with their ids.
GET /accounts/{address}/identitiesThe addresses it can send as.
Terminal
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, unseenMark read or unread.
flag, unflagFlag.
archive, trash, restoreArchive, move to Trash, bring back from Trash.
moveInto folder_id.
spam, ignoreMark as spam, or file into Ignore.
prioritySet level: high, medium, low or none.
Terminal
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.