Inboxes
Create and manage Inboxes A sending access key can call only these Inboxes endpoints: `POST /inboxes/{inbox_id}/threads/{thread_id}/emails/{email_id}/reply`, `POST /inboxes/{inbox_id}/threads/{thread_id}/emails/{email_id}/forward`, `POST /inboxes/{inbox_id}/drafts` and `POST /inboxes/{inbox_id}/drafts/{draft_id}/send`. When the key is limited to one domain, the inbox address must be on that domain, or the request returns a 403. Every other Inboxes endpoint needs a full access API key, and a sending access key returns a 401 `restricted_api_key`.
Retrieve a list of inboxes
GET /inboxes
Returns the inboxes of the team, newest first. The list items carry fewer fields than a single inbox. Retrieve an inbox to get all its fields. The after and before cursors take an inbox ID, and only one of them can be passed, or the request returns a 422. A value that is not a UUID returns a 422, and an unknown ID returns a 404.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
before | string | no | Return items before this cursor. |
Example
curl -X GET "$SESAMESEND_URL/inboxes" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
"name": "Customer Support",
"email_address": "support@example.com",
"from_name": "Ada from Support",
"unread": 3,
"last_received": "2026-08-05T14:03:11.229Z",
"created_at": "2026-08-01T09:12:44.512Z",
"updated_at": "2026-08-03T10:20:05.118Z"
}
]
}Create an inbox
POST /inboxes
Creates an inbox that sends and receives email at an address on one of your domains. The domain must belong to the team. Without forwarding, the domain must have receiving enabled, with DKIM and SPF verified and the inbound MX record verified or pending. With forwarding set to true, the domain only needs DKIM and SPF verified for sending, and sesameSend generates a receiving_address on the team inbound domain, and a team without an inbound domain gets a 422. A domain that does not meet these rules returns a 422 validation_error. An address or receiving address that is already in use returns a 409. A team that has reached the inbox limit of its plan returns a 403 validation_error. A blocked account returns a 451.
Body
| Field | Type | Required | Description |
|---|---|---|---|
email_address | string | yes | The inbox email address on one of your domains. The API trims and lowercases it. The part before the @ is at most 64 characters and contains only letters, numbers, and . _ % -. A + returns a 422. It cannot start or end with a dot or contain two dots in a row. |
name | string | no | Internal name for the inbox. Recipients do not see it. Max 64 characters. Defaults to email_address. |
from_name | string | no | The name recipients see when mail is sent from this inbox. A plain name, not a Name <email> address. Max 78 characters. It cannot contain a colon, <, >, line breaks, or other control characters. An email address inside the name must be on a domain the team has verified for sending. An empty string leaves it unset. |
forwarding | boolean | no | When true, sesameSend provisions a receiving address so you can receive mail without adding an MX record. The address is returned in receiving_address. |
Example
curl -X POST "$SESAMESEND_URL/inboxes" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email_address": "support@example.com",
"name": "Customer Support",
"from_name": "Ada from Support"
}'Responses
| Status | Description |
|---|---|
201 | OK |
{
"object": "inbox",
"id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1"
}Retrieve a single inbox by ID or email address
GET /inboxes/{inbox_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox",
"id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
"name": "Customer Support",
"email_address": "support@example.com",
"domain_id": "d91cd9bd-1176-453e-8fc1-35364d380206",
"receiving_address": null,
"from_name": "Ada from Support",
"unread": 3,
"drafts": 2,
"last_received": "2026-08-05T14:03:11.229Z",
"created_at": "2026-08-01T09:12:44.512Z",
"updated_at": "2026-08-03T10:20:05.118Z"
}Update an existing inbox by ID or email address
PATCH /inboxes/{inbox_id}
Updates the internal name of the inbox or the name recipients see when mail is sent from it. At least one of name or from_name is required.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | New internal name for the inbox. Recipients do not see it. Between 1 and 64 characters after trimming. |
from_name | string | no | The name recipients see when mail is sent from this inbox. A plain name, not a Name <email> address. Max 78 characters. It cannot contain a colon, <, >, line breaks, or other control characters. An email address inside the name must be on a domain the team has verified for sending. An empty string removes it. |
Example
curl -X PATCH "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d 'null'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox",
"id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1"
}Remove an existing inbox by ID or email address
DELETE /inboxes/{inbox_id}
Removes the inbox. An inbox that does not exist or was already removed returns a 404 not_found.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Example
curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox",
"id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
"deleted": true
}Retrieve the agent settings for an inbox
GET /inboxes/{inbox_id}/agent
Returns the agent settings of the inbox. An inbox without a configured agent returns empty settings: instructions and tone are null and actions is an empty array.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/agent" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_agent",
"instructions": "Answer refund questions yourself. Escalate legal threats.",
"tone": "concise_professional",
"actions": [
"draft_reply",
"add_labels"
]
}Update the agent settings for an inbox
PATCH /inboxes/{inbox_id}/agent
Updates the agent settings of the inbox. The agent is created when the inbox has none. Omitted fields keep their current value.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
instructions | string | null | no | Instructions the agent follows when it handles the threads of the inbox. Max 4000 characters. Leading and trailing whitespace is trimmed, and the trimmed value must not be empty. Send null to clear the instructions. |
tone | "concise_professional" | "concise_casual" | "expanded_professional" | "expanded_casual" | null | no | The tone the agent writes in. Send null to clear the tone. |
actions | "draft_reply" | "forward_thread" | "add_labels" | "assign_thread" | "mark_as_spam" | "archive" | "move_to_trash"[] | no | The actions the agent can take. Replaces the whole set. Duplicates are removed. Send an empty array to disable all actions. The old names archive_thread and delete_thread return a 422. Use archive and move_to_trash. |
Example
curl -X PATCH "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/agent" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d 'null'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_agent",
"id": "a1f84a4e-6f2b-4f0a-9c1d-8a2e5b3c7d90"
}Retrieve a list of inbox labels
GET /inboxes/{inbox_id}/labels
Returns every label on the inbox, oldest first. The list is not paginated.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/labels" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"data": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82",
"created_at": "2026-08-05T14:07:42.881Z"
}
]
}Create a label on an inbox
POST /inboxes/{inbox_id}/labels
A label is a named, colored tag that belongs to one inbox. An inbox can have at most 100 labels. Label names are unique per inbox, compared without case. A duplicate name or a full inbox returns a 422 validation_error.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | The name of the label. Max 64 characters. Leading and trailing whitespace is trimmed. Must not match another label on the inbox, compared without case. |
color | string | no | The color of the label, as a #RRGGBB hex color. It is stored in uppercase. When omitted, a random color from the dashboard palette is used. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/labels" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Urgent",
"color": "#E93D82"
}'Responses
| Status | Description |
|---|---|
201 | OK |
{
"object": "inbox_label",
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34"
}Update an existing inbox label
PATCH /inboxes/{inbox_id}/labels/{label_id}
Renames or recolors a label. Omitted fields keep their current value. A new name must not match another label on the inbox, compared without case, or the request returns a 422 validation_error.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
label_id | string | yes | The Label ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | A new name for the label. Max 64 characters. Leading and trailing whitespace is trimmed. Must not match another label on the inbox, compared without case. |
color | string | no | A new color for the label, as a #RRGGBB hex color. It is stored in uppercase. |
Example
curl -X PATCH "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/labels/<label_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Billing",
"color": "#F76B15"
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_label",
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34"
}Remove an existing inbox label
DELETE /inboxes/{inbox_id}/labels/{label_id}
Deletes the label and removes it from every thread that carries it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
label_id | string | yes | The Label ID. |
Example
curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/labels/<label_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_label",
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"deleted": true
}Retrieve a list of inbox threads
GET /inboxes/{inbox_id}/threads
Returns the threads in an inbox, most recently active first. A thread is a conversation made up of one or more emails. The after and before cursors take a thread ID, and only one of them can be passed. A cursor that is not a UUID, such as a date, returns a 422 validation_error. A cursor thread that is not in the selected folders returns a 404. To find threads by text, sender, recipient, attachment, or date, use the search threads endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
folders | "inbox" | "archive" | "spam" | "sent" | "trash"[] | no | Comma-separated folders to list, for example inbox,sent. Repeating the parameter returns a 422 validation_error. A thread is returned when any of its emails is in one of the folders, so a thread in inbox with an email you sent matches both inbox and sent. Defaults to inbox, or to inbox,archive,sent when labels is set. spam and trash are only included when you name them. |
labels | string[] | no | Comma-separated label IDs. Returns threads with any of these labels. Up to 50 IDs. An ID that does not exist in the inbox returns a 404. Repeating the parameter returns a 422 validation_error. |
read | boolean | no | true returns threads where every email is read. false returns threads with at least one unread email. Only the literal values true and false are accepted. |
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
before | string | no | Return items before this cursor. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": true,
"data": [
{
"id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"subject": "Refund for order 1041",
"from": "ada@example.org",
"to": [
"support@example.com"
],
"cc": [],
"bcc": [],
"labels": [
{}
],
"email_count": 2,
"has_attachment": true,
"has_draft": false,
"read": false,
"received_at": "2026-08-05T14:03:11.229Z",
"folder": "inbox"
}
]
}Search the threads of an inbox
GET /inboxes/{inbox_id}/threads/search
Finds threads by the text of their emails, who sent or received them, whether they have attachments, and their dates. Results are ordered by latest activity, newest first, and paginate like the list threads endpoint, so a cursor that is not a thread ID returns a 422. Search can be up to about a minute behind new emails. Different parameters combine, so a thread must match all of them. folders, labels, and read apply to the thread. query, from, to, cc, bcc, has_attachment, start_date, and end_date must all match the same email in the thread. When any of these email filters is set, the matching email must itself be in one of folders. For sent, that means an email the inbox sent. When more than 10,000 threads match, search covers the 10,000 with the newest matching email.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
query | string | no | Free text to search for in the subject, body, sender, recipients, and attachment names. Every word must match. Wrap words in double quotes to match an exact phrase. Start a word or quoted phrase with - to exclude it. Max 256 characters and 32 words. |
from | string[] | no | Comma-separated senders. Each value matches part of the sender's address or name, without case. Returns threads that match any of them. Up to 20 values. Repeating the parameter returns a 422 validation_error. |
to | string[] | no | Comma-separated recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error. |
cc | string[] | no | Comma-separated CC recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error. |
bcc | string[] | no | Comma-separated BCC recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error. |
has_attachment | boolean | no | true matches emails with an attachment. false matches emails without one. Only the literal values true and false are accepted. |
start_date | string | no | Matches emails sent on or after this date. Accepts a date like 2026-09-01 or an ISO 8601 timestamp, in UTC unless the timestamp has an offset. An empty value returns a 422. |
end_date | string | no | Matches emails sent on or before this date. Same formats as start_date. A date covers that whole day, so start_date=2026-09-01&end_date=2026-09-30 covers all of September. A timestamp is used as given. An end_date before start_date returns a 422 validation_error. An empty value returns a 422. |
folders | "inbox" | "archive" | "spam" | "sent" | "trash"[] | no | Comma-separated folders to search, for example inbox,sent. Repeating the parameter returns a 422 validation_error. A thread is returned when any of its emails is in one of the folders. Defaults to inbox, or to inbox,archive,sent when labels is set. spam and trash are only included when you name them. |
labels | string[] | no | Comma-separated label IDs. Returns threads with any of these labels. Up to 50 IDs. An ID that does not exist in the inbox returns a 404. Repeating the parameter returns a 422 validation_error. |
read | boolean | no | true returns threads where every email is read. false returns threads with at least one unread email. Only the literal values true and false are accepted. |
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
before | string | no | Return items before this cursor. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/search" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": true,
"data": [
{
"id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"subject": "Refund for order 1041",
"from": "ada@example.org",
"to": [
"support@example.com"
],
"cc": [],
"bcc": [],
"labels": [
{}
],
"email_count": 2,
"has_attachment": true,
"has_draft": false,
"read": false,
"received_at": "2026-08-05T14:03:11.229Z",
"folder": "inbox",
"matched_email_id": "e8a3f1c6-2b9d-4e5a-a7c4-9d1b6f3e2a80"
}
]
}Retrieve a single inbox thread
GET /inboxes/{inbox_id}/threads/{thread_id}
Returns the thread summary. The emails in the thread are listed with the list thread emails endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_thread",
"id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"subject": "Refund for order 1041",
"folder": "inbox",
"labels": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82"
}
],
"read": false
}Update an existing inbox thread
PATCH /inboxes/{inbox_id}/threads/{thread_id}
Marks a thread read or unread, or moves it to a folder. At least one of read or folder is required. To change the labels of a thread, use the add, set, and remove thread labels endpoints. This endpoint ignores the removed add_label_ids and remove_label_ids fields, so a body with only those fields returns a 422 validation_error. Moving a thread out of trash restores it and clears its deletion deadline. The changes apply in this order: read, then folder. They are not atomic.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
read | boolean | no | Marks every email in the thread read or unread. |
folder | "inbox" | "archive" | "spam" | "trash" | no | Moves the thread to this folder. sent is assigned automatically and cannot be set. |
Example
curl -X PATCH "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d 'null'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_thread",
"id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"subject": "Refund for order 1041",
"folder": "inbox",
"labels": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82"
}
],
"read": false
}Remove an existing inbox thread
DELETE /inboxes/{inbox_id}/threads/{thread_id}
Moves the thread to trash and schedules it for deletion in 30 days. This is reversible. To restore the thread, update its folder to inbox, archive, or spam, which also clears the deletion deadline.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Example
curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_thread",
"id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"deleted": true
}Add labels to an inbox thread
POST /inboxes/{inbox_id}/threads/{thread_id}/labels
Applies one or more labels to the thread. Labels already on the thread stay on it. The response lists every label on the thread after the change. A label ID that is not a label of the inbox returns a 404 Label not found., and nothing changes. A thread that does not exist in the inbox returns a 404 Thread not found.. To replace the labels of the thread, use the set thread labels endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
labels | string[] | yes | The IDs of the labels to apply to the thread. Between 1 and 10 IDs, each a label of the inbox. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/labels" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"labels": [
"7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34"
]
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"data": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82"
}
]
}Set the labels of an inbox thread
PUT /inboxes/{inbox_id}/threads/{thread_id}/labels
Replaces every label on the thread with the given labels, in one atomic change. Labels on the thread that are not in the list are taken off it. The labels themselves are kept. An empty array takes every label off the thread. The response lists every label on the thread after the change. A label ID that is not a label of the inbox returns a 404 Label not found., and nothing changes. A thread that does not exist in the inbox returns a 404 Thread not found..
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
labels | string[] | yes | The IDs of the labels the thread carries after the change. Up to 100 IDs, each a label of the inbox. Pass an empty array to take every label off the thread. |
Example
curl -X PUT "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/labels" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"labels": [
"7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34"
]
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"data": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82"
}
]
}Remove a label from an inbox thread
DELETE /inboxes/{inbox_id}/threads/{thread_id}/labels/{label_id}
Takes one label off the thread. The label itself is kept, and stays on every other thread that carries it. To delete the label, use the remove inbox label endpoint. The response lists every label on the thread after the change. A label that is not on the thread returns a 200 with the current labels. A label ID that is not a label of the inbox returns a 404 Label not found.. A thread that does not exist in the inbox returns a 404 Thread not found..
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
label_id | string | yes | The Label ID. |
Example
curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/labels/<label_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"data": [
{
"id": "7f9c1d2e-4a6b-4c3d-8e15-9b0a7c6d5e34",
"name": "Urgent",
"color": "#E93D82"
}
]
}Retrieve a list of thread emails
GET /inboxes/{inbox_id}/threads/{thread_id}/emails
Returns the messages of a thread, oldest first. Pass the id of the last message as after to get the next, newer page. Pass the id of the first message as before to get the previous, older page. Passing both after and before, or a cursor that is not a UUID, returns a 422. A cursor that is not a message of the thread returns a 404.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
before | string | no | Return items before this cursor. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/emails" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
"direction": "inbound",
"from": "Ada Lovelace <ada@example.org>",
"to": [
"support@example.com"
],
"cc": [],
"bcc": [],
"reply_to": [
"replies@example.org"
],
"subject": "Refund for order 1041",
"message_id": "<1041@example.org>",
"html": "<p>Could I get a refund for order 1041?</p>",
"text": "Could I get a refund for order 1041?",
"attachments": [
{}
],
"read": false,
"received_at": "2026-08-05T14:03:11.229Z"
}
]
}Retrieve a single thread email
GET /inboxes/{inbox_id}/threads/{thread_id}/emails/{email_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
email_id | string | yes | The Email ID, as returned in data[].id by the list thread emails endpoint. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/emails/<email_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"id": "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
"direction": "inbound",
"from": "Ada Lovelace <ada@example.org>",
"to": [
"support@example.com"
],
"cc": [],
"bcc": [],
"reply_to": [
"replies@example.org"
],
"subject": "Refund for order 1041",
"message_id": "<1041@example.org>",
"html": "<p>Could I get a refund for order 1041?</p>",
"text": "Could I get a refund for order 1041?",
"attachments": [
{
"id": "9d4f2b81-6c3a-4e7d-8b12-0a5c6d7e8f90",
"filename": "receipt.pdf",
"size": 20841
}
],
"read": false,
"received_at": "2026-08-05T14:03:11.229Z"
}Reply to a thread email
POST /inboxes/{inbox_id}/threads/{thread_id}/emails/{email_id}/reply
Sends a reply from the inbox address right away, with no stored draft. The to recipients come from the message you reply to. For a message the inbox received, the reply goes to its Reply-To addresses, or to its sender when it has no Reply-To. For a message the inbox sent, the reply goes to that message's to recipients. Set reply_all to also copy the other recipients of the message. The reply threads under the message through the In-Reply-To and References headers. When no recipient can be found for the reply, the request returns a 422. The whole email, encoded, can be at most 40 MB, or the request returns a 422.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
email_id | string | yes | The Email ID of the message to reply to, as returned in data[].id by the list thread emails endpoint. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | A unique key for the request, so the reply is sent only once. A retry with the same key within 24 hours returns the first successful (2xx) response, with the idempotent-replayed: true header. A failed request is not stored, so it can be retried with the same key. Reusing the key with a different body, or while the first request is still running, returns a 409. An empty key, or one longer than 256 characters, returns a 400 invalid_idempotency_key. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
cc | string | string[] | null | no | CC recipient email address. For multiple addresses, send as an array of strings. Without reply_all, the reply copies only these addresses. With reply_all, these addresses are merged with the copied recipients, without duplicates. cc and bcc combined must be fewer than 50 addresses. After the to recipients are added, the reply cannot exceed 50 recipients. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
bcc | string | string[] | null | no | BCC recipient email address. For multiple addresses, send as an array of strings. BCC recipients of the original message are never copied. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
html | string | no | The HTML body of the reply. |
text | string | no | The plain-text body of the reply. |
subject | string | no | The subject of the reply. Cannot be only whitespace or contain a line break. When omitted, the thread subject is used, prefixed with Re: if it does not already start with it. |
reply_all | boolean | no | Reply to everyone on the original message. For a message the inbox received, the reply goes to its Reply-To addresses, or to its sender when it has none, and copies the other addresses of its To header and its cc recipients in cc. For a message the inbox sent, the reply goes to that message's Reply-To addresses when they are not the inbox address, otherwise to its to recipients, and copies its cc recipients. The inbox address is always excluded, and duplicates are removed. |
attachments | array | null | no | Files to attach, as on POST /emails. Each one needs content or path. The content of all files can total at most 25 MB. A path file does not count toward the 25 MB, because it is fetched when the email is sent. An empty file, a blocked file type, a path that does not start with http or that starts with http://localhost:, or a content_type that is not a valid MIME type returns a 422. Other path problems fail the email when it is sent, not the request. |
headers | object | null | no | Custom headers to add to the email. The In-Reply-To, References and Reply-To headers are set by sesameSend and cannot be set here. Sending one of them, in any letter case, returns a 422. Header names cannot be empty, and names and values cannot contain line breaks or null characters, or the request returns a 422. null means no custom headers. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/emails/<email_id>/reply" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d 'null'Responses
| Status | Description |
|---|---|
200 | OK |
{
"id": "6a0c8e58-3d9e-4f7a-8b14-2e3f4a5b6c71"
}Forward a thread email
POST /inboxes/{inbox_id}/threads/{thread_id}/emails/{email_id}/forward
Forwards a message from the inbox address right away, with no stored draft. The original message is quoted under a forwarded-message banner, below the optional html or text note. The attachments of the original message are sent with the forward, together with any attachments you add. The request returns a 422 when they exceed 25 MB of content in total. An original attachment that was sent from a URL (path) cannot be forwarded, and the request returns a 422. The whole email, encoded, can be at most 40 MB, or the request returns a 422.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
thread_id | string | yes | The Thread ID. |
email_id | string | yes | The Email ID of the message to forward, as returned in data[].id by the list thread emails endpoint. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | A unique key for the request, so the forward is sent only once. A retry with the same key within 24 hours returns the first successful (2xx) response, with the idempotent-replayed: true header. A failed request is not stored, so it can be retried with the same key. Reusing the key with a different body, or while the first request is still running, returns a 409. An empty key, or one longer than 256 characters, returns a 400 invalid_idempotency_key. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | string[] | yes | Recipient email address. For multiple addresses, send as an array of strings. Must name at least one address. to, cc and bcc combined cannot exceed 50 recipients. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
cc | string | string[] | null | no | CC recipient email address. For multiple addresses, send as an array of strings. Counts toward the 50-recipient limit. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
bcc | string | string[] | null | no | BCC recipient email address. For multiple addresses, send as an array of strings. Counts toward the 50-recipient limit. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
html | string | no | An HTML note sent above the quoted original. |
text | string | no | A plain-text note sent above the quoted original. |
subject | string | no | The subject of the forward. Cannot be only whitespace or contain a line break. When omitted, the thread subject is used, prefixed with Fwd: if it does not already start with it. |
attachments | array | null | no | Files to attach, as on POST /emails. Each one needs content or path. They share one limit with the attachments of the original message, which the forward also sends. Together they can have at most 25 MB of content. A path file does not count toward the 25 MB, because it is fetched when the email is sent. An empty file, a blocked file type, a path that does not start with http or that starts with http://localhost:, or a content_type that is not a valid MIME type returns a 422. Other path problems fail the email when it is sent, not the request. |
headers | object | null | no | Custom headers to add to the email. The In-Reply-To, References and Reply-To headers are set by sesameSend and cannot be set here. Sending one of them, in any letter case, returns a 422. Header names cannot be empty, and names and values cannot contain line breaks or null characters, or the request returns a 422. null means no custom headers. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>/emails/<email_id>/forward" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": [
"colleague@example.org"
],
"cc": [
"billing@example.com"
],
"bcc": [
"records@example.com"
],
"html": "<p>Flagging this refund request for you.</p>",
"text": "Flagging this refund request for you.",
"subject": "Fwd: Refund for order 1041",
"headers": {
"X-Ticket-Id": "4821"
}
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"id": "6a0c8e58-3d9e-4f7a-8b14-2e3f4a5b6c71"
}Retrieve a list of drafts
GET /inboxes/{inbox_id}/drafts
Returns the unsent drafts on the inbox, most recently updated first. The after and before cursors take a Draft ID from the current page, and only one of them can be passed. A cursor that is not a UUID, or both cursors together, return a 422. A cursor that is not an unsent draft on this inbox returns a 404.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
before | string | no | Return items before this cursor. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32",
"type": "standalone",
"to": [
"ada@example.org"
],
"cc": [],
"bcc": [],
"subject": "Refund for order 1041",
"snippet": "Refund issued for order 1041.",
"thread_id": null,
"reply_to_email_id": null,
"updated_at": "2026-08-05T14:12:04.110Z",
"attachments": [
{}
]
}
]
}Create a draft
POST /inboxes/{inbox_id}/drafts
Creates an unsent draft on the inbox. Omit thread_id and reply_to_email_id for a draft that starts a new thread. Pass both together for a reply draft in an existing thread. A reply draft without to is addressed to the sender of the email it replies to, or to its Reply-To when set. For an email the inbox sent, it defaults to that email's to recipients. Send to: [] to leave it empty. At least one of to, cc, bcc, subject, text, html or attachments must be non-empty. The combined recipients of to, cc and bcc cannot exceed 50. Attachments are stored on the draft, so a path file is downloaded when the request is made. Returns 201 for a new draft. Only one unsent reply draft can target an email, so a reply draft request for an email that already has one returns 200 with the ID of the existing draft. An unknown thread_id, or a reply_to_email_id that is not in that thread, returns a 404. That request ignores every other field, except attachments, which replaces the attachments of the existing draft when sent. A reply draft created without subject stores an empty subject. When it is sent, it takes the thread subject, prefixed with Re: when it does not already start with it.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | A unique key for the request, so the draft is created only once. A retry with the same key within 24 hours returns the first successful (2xx) response, with the idempotent-replayed: true header. A failed request is not stored, so it can be retried with the same key. Reusing the key with a different body, or while the first request is still running, returns a 409. An empty key, or one longer than 256 characters, returns a 400 invalid_idempotency_key. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | string[] | null | no | The recipients. For multiple addresses, send an array of strings. Each value can include a friendly name, for example Ada Lovelace <ada@example.org>. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
cc | string | string[] | null | no | The CC recipients. For multiple addresses, send an array of strings. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
bcc | string | string[] | null | no | The BCC recipients. For multiple addresses, send an array of strings. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
subject | string | null | no | The subject. Max 2000 characters. A string that is only whitespace, or that contains a line break, is rejected. |
html | string | null | no | The HTML body. |
text | string | null | no | The plain text body. |
attachments | array | null | no | Files to store on the draft. Each one needs a filename and either content or a path URL. A path file is downloaded when the request is made and stored on the draft. When both are sent, path is ignored. A content_id returns a 422. The files on a draft, downloaded ones included, can total at most 25 MB. A path that does not start with http or https, or that cannot be downloaded, returns a 422, and so does a request whose downloads take more than 20 seconds together. An empty file or a blocked file type returns a 422. |
thread_id | string | no | The Thread ID to reply in. Must be sent with reply_to_email_id. |
reply_to_email_id | string | no | The Email ID to reply to, as returned in data[].id by the list thread emails endpoint. Must be sent with thread_id. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": [
"ada@example.org"
],
"subject": "Refund for order 1041",
"html": "<p>Refund issued for order 1041.</p>",
"text": "Refund issued for order 1041.",
"thread_id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
"reply_to_email_id": "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60"
}'Responses
| Status | Description |
|---|---|
200 | The reply draft for this email already exists. The response holds the ID of the existing draft, and the request fields other than attachments are not applied. |
201 | OK |
{
"object": "inbox_draft",
"id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32"
}Retrieve a single draft
GET /inboxes/{inbox_id}/drafts/{draft_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
draft_id | string | yes | The Draft ID. |
Example
curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_draft",
"id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32",
"type": "standalone",
"to": [
"ada@example.org"
],
"cc": [],
"bcc": [],
"subject": "Refund for order 1041",
"html": "<p>Refund issued for order 1041.</p>",
"text": "Refund issued for order 1041.",
"thread_id": null,
"reply_to_email_id": null,
"email_id": null,
"created_at": "2026-08-05T14:12:04.110Z",
"updated_at": "2026-08-05T14:12:04.110Z",
"attachments": [
{
"id": "5c1e9d2a-7b3f-4e8a-9c6d-2f0a1b3c4d5e",
"filename": "receipt.pdf",
"content_type": "application/pdf",
"size": 20841
}
]
}Update an existing draft
PATCH /inboxes/{inbox_id}/drafts/{draft_id}
Updates the content of an unsent draft. Omitted fields are left unchanged. Send at least one of to, cc, bcc, subject, text, html or attachments. Sending attachments replaces every attachment on the draft. A request that sets text or html replaces the whole body. The body part you omit from that request becomes null. The merged draft must still contain at least one non-empty field, and its combined recipients cannot exceed 50. A draft that was already sent, or that changed during the request, returns a 409. The response holds only the Draft ID. Retrieve the draft to read its content.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
draft_id | string | yes | The Draft ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | string[] | null | no | The recipients. For multiple addresses, send an array of strings. Each value can include a friendly name. Pass null to clear. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
cc | string | string[] | null | no | The CC recipients. Pass null or [] to clear. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
bcc | string | string[] | null | no | The BCC recipients. Pass null or [] to clear. Each address is email@example.com or Name <email@example.com>. An address that is not valid returns a 422. |
subject | string | null | no | The subject. Max 2000 characters. Cannot be only whitespace or contain a line break. Pass null to clear. |
html | string | null | no | The HTML body. Pass null to clear. |
text | string | null | no | The plain text body. Pass null to clear. |
attachments | array | null | no | Files to store on the draft. Each one needs a filename and either content or a path URL. A path file is downloaded when the request is made and stored on the draft. When both are sent, path is ignored. A content_id returns a 422. The files on a draft, downloaded ones included, can total at most 25 MB. A path that does not start with http or https, or that cannot be downloaded, returns a 422, and so does a request whose downloads take more than 20 seconds together. An empty file or a blocked file type returns a 422. Sending the field replaces every attachment on the draft. Send [] to remove them all. null also removes them all. |
Example
curl -X PATCH "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d 'null'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_draft",
"id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32"
}Remove an existing draft
DELETE /inboxes/{inbox_id}/drafts/{draft_id}
Discards an unsent draft. A draft that was already sent, or that changed during the request, returns a 409.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
draft_id | string | yes | The Draft ID. |
Example
curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "inbox_draft",
"id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32",
"deleted": true
}Send a draft
POST /inboxes/{inbox_id}/drafts/{draft_id}/send
Sends the draft from the inbox address. A reply draft is sent in its thread. A draft without a thread starts a new thread. The draft must have at least one to recipient and html or text, or the request returns a 422. A standalone draft also needs a non-empty subject. A reply draft with an empty subject is sent with the thread subject, prefixed with Re: when it does not already start with it. A draft that was already sent returns a 409. The request body is optional and takes only headers. The whole email, encoded, can be at most 40 MB, or the request returns a 422.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox_id | string | yes | The Inbox ID or the inbox email address, such as support@example.com. A value that contains @ must be a valid email address, and any other value must be a UUID, or the request returns a 422. The address match is case-insensitive and never falls back to the inbox name. An address that matches no inbox returns a 404. |
draft_id | string | yes | The Draft ID. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | A unique key for the request, so the draft is sent only once. A retry with the same key within 24 hours returns the first successful (2xx) response, with the idempotent-replayed: true header. A failed request is not stored, so it can be retried with the same key. Reusing the key with a different body, or while the first request is still running, returns a 409. An empty key, or one longer than 256 characters, returns a 400 invalid_idempotency_key. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
headers | object | null | no | Custom headers to add to the email. The In-Reply-To, References and Reply-To headers are set by sesameSend and cannot be set here. Sending one of them, in any letter case, returns a 422. Header names cannot be empty, and names and values cannot contain line breaks or null characters, or the request returns a 422. null means no custom headers. |
Example
curl -X POST "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>/send" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"headers": {
"X-Ticket-Id": "4821"
}
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"id": "6a0c8e58-3d9e-4f7a-8b14-2e3f4a5b6c71"
}