Skip to Content
sesameSend

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

NameTypeRequiredDescription
limitintegernoNumber of items to return.
afterstringnoReturn items after this cursor.
beforestringnoReturn items before this cursor.

Example

curl -X GET "$SESAMESEND_URL/inboxes" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

FieldTypeRequiredDescription
email_addressstringyesThe 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.
namestringnoInternal name for the inbox. Recipients do not see it. Max 64 characters. Defaults to email_address.
from_namestringnoThe 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.
forwardingbooleannoWhen 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

StatusDescription
201OK
{
  "object": "inbox",
  "id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1"
}

Retrieve a single inbox by ID or email address

GET /inboxes/{inbox_id}

Path parameters

NameTypeRequiredDescription
inbox_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

FieldTypeRequiredDescription
namestringnoNew internal name for the inbox. Recipients do not see it. Between 1 and 64 characters after trimming.
from_namestringnoThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

FieldTypeRequiredDescription
instructionsstring | nullnoInstructions 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" | nullnoThe 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"[]noThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

FieldTypeRequiredDescription
namestringyesThe name of the label. Max 64 characters. Leading and trailing whitespace is trimmed. Must not match another label on the inbox, compared without case.
colorstringnoThe 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

StatusDescription
201OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Label ID.

Body

FieldTypeRequiredDescription
namestringnoA 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.
colorstringnoA 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Label ID.

Example

curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/labels/<label_id>" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

NameTypeRequiredDescription
folders"inbox" | "archive" | "spam" | "sent" | "trash"[]noComma-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.
labelsstring[]noComma-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.
readbooleannotrue 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.
limitintegernoNumber of items to return.
afterstringnoReturn items after this cursor.
beforestringnoReturn items before this cursor.

Example

curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

NameTypeRequiredDescription
querystringnoFree 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.
fromstring[]noComma-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.
tostring[]noComma-separated recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error.
ccstring[]noComma-separated CC recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error.
bccstring[]noComma-separated BCC recipients, matched the same way as from. Up to 20 values. Repeating the parameter returns a 422 validation_error.
has_attachmentbooleannotrue matches emails with an attachment. false matches emails without one. Only the literal values true and false are accepted.
start_datestringnoMatches 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_datestringnoMatches 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"[]noComma-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.
labelsstring[]noComma-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.
readbooleannotrue 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.
limitintegernoNumber of items to return.
afterstringnoReturn items after this cursor.
beforestringnoReturn 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Example

curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Body

FieldTypeRequiredDescription
readbooleannoMarks every email in the thread read or unread.
folder"inbox" | "archive" | "spam" | "trash"noMoves 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Example

curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/<thread_id>" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Body

FieldTypeRequiredDescription
labelsstring[]yesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Body

FieldTypeRequiredDescription
labelsstring[]yesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.
label_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.

Query parameters

NameTypeRequiredDescription
limitintegernoNumber of items to return.
afterstringnoReturn items after this cursor.
beforestringnoReturn 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.
email_idstringyesThe 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.
email_idstringyesThe Email ID of the message to reply to, as returned in data[].id by the list thread emails endpoint.

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoA 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

FieldTypeRequiredDescription
ccstring | string[] | nullnoCC 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.
bccstring | string[] | nullnoBCC 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.
htmlstringnoThe HTML body of the reply.
textstringnoThe plain-text body of the reply.
subjectstringnoThe 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_allbooleannoReply 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.
attachmentsarray | nullnoFiles 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.
headersobject | nullnoCustom 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Thread ID.
email_idstringyesThe Email ID of the message to forward, as returned in data[].id by the list thread emails endpoint.

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoA 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

FieldTypeRequiredDescription
tostring | string[]yesRecipient 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.
ccstring | string[] | nullnoCC 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.
bccstring | string[] | nullnoBCC 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.
htmlstringnoAn HTML note sent above the quoted original.
textstringnoA plain-text note sent above the quoted original.
subjectstringnoThe 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.
attachmentsarray | nullnoFiles 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.
headersobject | nullnoCustom 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

NameTypeRequiredDescription
limitintegernoNumber of items to return.
afterstringnoReturn items after this cursor.
beforestringnoReturn items before this cursor.

Example

curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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

NameTypeRequiredDescription
Idempotency-KeystringnoA 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

FieldTypeRequiredDescription
tostring | string[] | nullnoThe 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.
ccstring | string[] | nullnoThe 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.
bccstring | string[] | nullnoThe 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.
subjectstring | nullnoThe subject. Max 2000 characters. A string that is only whitespace, or that contains a line break, is rejected.
htmlstring | nullnoThe HTML body.
textstring | nullnoThe plain text body.
attachmentsarray | nullnoFiles 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_idstringnoThe Thread ID to reply in. Must be sent with reply_to_email_id.
reply_to_email_idstringnoThe 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

StatusDescription
200The 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.
201OK
{
  "object": "inbox_draft",
  "id": "c3a1e8b4-2d5f-4a7c-9e10-6b8d7f5a4c32"
}

Retrieve a single draft

GET /inboxes/{inbox_id}/drafts/{draft_id}

Path parameters

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Draft ID.

Example

curl -X GET "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Draft ID.

Body

FieldTypeRequiredDescription
tostring | string[] | nullnoThe 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.
ccstring | string[] | nullnoThe 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.
bccstring | string[] | nullnoThe 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.
subjectstring | nullnoThe subject. Max 2000 characters. Cannot be only whitespace or contain a line break. Pass null to clear.
htmlstring | nullnoThe HTML body. Pass null to clear.
textstring | nullnoThe plain text body. Pass null to clear.
attachmentsarray | nullnoFiles 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

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Draft ID.

Example

curl -X DELETE "$SESAMESEND_URL/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/drafts/<draft_id>" \
  -H "Authorization: Bearer $OPENSEND_API_KEY"

Responses

StatusDescription
200OK
{
  "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

NameTypeRequiredDescription
inbox_idstringyesThe 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_idstringyesThe Draft ID.

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoA 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

FieldTypeRequiredDescription
headersobject | nullnoCustom 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

StatusDescription
200OK
{
  "id": "6a0c8e58-3d9e-4f7a-8b14-2e3f4a5b6c71"
}