Knobs Mail is thread-centric: inbound and outbound messages group into threads per mailbox. The API reads threads and messages, sends outbound mail from any of your active addresses, and exposes the compose AI assists.
All routes are workspace-scoped and accept a session JWT or API key. You only ever see mail addressed to (or sent from) your own mailboxes and aliases.
Threads & messages
Section titled “Threads & messages”| Endpoint | Description |
|---|---|
GET /v1/workspaces/{wid}/mail/threads |
List your threads, newest first; ?folder= (inbox/archive/trash/spam/sent) and ?limit= |
GET /v1/workspaces/{wid}/mail/threads/{tid} |
Thread with its ordered messages |
GET /v1/workspaces/{wid}/mail/threads/{tid}/messages |
The messages in a thread (?limit=) |
GET /v1/workspaces/{wid}/mail/messages/{mid}/raw-url |
Short-lived signed URL for the raw MIME → {url} |
GET /v1/workspaces/{wid}/mail/messages/{mid}/attachments/{idx}/download-url |
Signed URL for attachment idx → {url} (409 until extraction finishes) |
curl -H "Authorization: Bearer knak_..." \ "https://api.knobs.io/v1/workspaces/{wid}/mail/threads?folder=inbox&limit=25"{ "items": [ { "id": "t_8c1f…", "subject": "Q3 planning", "snippet": "Here's the draft agenda…", "folder": "inbox", "unread": true, "starred": false, "lastMessageAt": "2026-07-16T15:02:11Z" } ], "nextPageToken": ""}Sending
Section titled “Sending”| Endpoint | Description |
|---|---|
POST /v1/workspaces/{wid}/mail/messages:send |
Send a message |
POST /v1/workspaces/{wid}/mail/drafts/{rpc...} |
Draft RPCs — currently {draftId}:send, equivalent to messages:send |
Send a message
Section titled “Send a message”curl -X POST https://api.knobs.io/v1/workspaces/{wid}/mail/messages:send \ -H "Authorization: Bearer knak_..." \ -H "Content-Type: application/json" \ -d '{ "from": "jane@acme.knobs.io", "to": ["sam@example.com"], "cc": [], "subject": "Q3 planning", "text": "Draft agenda attached.", "html": "<p>Draft agenda attached.</p>", "clientMutationId": "0d5e0a4e-8f0f-4f57-a2ff-0f6a4b1c9d21", "replyToMessageId": "", "attachmentNodeIds": ["n_77aa…"] }'Returns 201 with the stored message. Notes:
frommust be one of your active mailboxes or aliases (403 sender_not_authorizedotherwise) on a verified domain.replyToMessageIdthreads the send as a reply and sets the reply headers.attachmentNodeIdsreference Drive file nodes; total attachment size is capped at 25 MiB.clientMutationIdmakes retries safe.
Thread actions
Section titled “Thread actions”| Endpoint | Description |
|---|---|
POST /v1/workspaces/{wid}/mail/threads/{tid}/read |
{read: true|false} — mark read/unread |
POST /v1/workspaces/{wid}/mail/threads/{tid}/move |
{folder} — move to inbox/archive/trash/spam |
POST /v1/workspaces/{wid}/mail/threads/{tid}/star |
{starred: true|false} |
Each returns the updated thread.
AI assists
Section titled “AI assists”Synchronous single-turn generations for the composer. Results are ephemeral — returned for review, never persisted. Rate-limited per user (429 resource_exhausted).
| Endpoint | Description |
|---|---|
POST /v1/workspaces/{wid}/mail/ai:suggest-reply |
{threadId, guidance?} → a drafted reply |
POST /v1/workspaces/{wid}/mail/ai:improve-draft |
{text, subject?, threadId?, to?} → a cleaned-up draft |
POST /v1/workspaces/{wid}/mail/ai:summarize-thread |
{threadId} → a thread digest |
All three return the same shape:
{ "text": "Thanks Sam — Wednesday works…", "model": "…", "inputTokens": 812, "outputTokens": 96 }Read aloud
Section titled “Read aloud”| Endpoint | Description |
|---|---|
POST /v1/voice/read-aloud |
{workspaceId, entityType, entityId} → synthesized audio bytes (not JSON; Content-Type is the audio MIME) |
entityType is one of mail.message, mail.thread, mail.thread.summary. The entity is resolved and ACL-checked server-side — you pass a reference, never raw text.
Undelivered mail (admin)
Section titled “Undelivered mail (admin)”Inbound messages to a nonexistent address are shelved for 30 days rather than dropped. Admins can inspect and resolve them:
| Endpoint | Description |
|---|---|
GET /v1/workspaces/{wid}/mail/rejections |
List undelivered mail, newest first |
POST /v1/workspaces/{wid}/mail/rejections/{rid}/redeliver |
Deliver into the (now-created) mailbox — 409 still_unroutable if the address still doesn’t exist |
POST /v1/workspaces/{wid}/mail/rejections/{rid}/dismiss |
Resolve without delivering |
Related
Section titled “Related”- Domains, mailboxes & aliases — where addresses come from.
- Tasks and Calendar — create a task or event from a thread.