Skip to main content
Emails are flat: one object per message, across every mailbox you have connected. Conversations are not fetched as a whole. Instead, threadId ties messages together, and you can ask for just the newest message of each conversation.

Scopes

List results never include the message body. They carry a snippet preview instead, which keeps paging fast no matter how large the messages are. Fetch a single email when you need to read it.

List emails

GET /v1/emails is cursor-paginated, newest first. Keep requesting with ?cursor=meta.nextCursor until meta.hasMore is false.
Response
Filters combine freely: mailbox (comma-separated addresses), campaignId, threadId, leadId, isUnread, type (sent or received), folder (inbox, untracked, important, snoozed, or archived), since, until, and search. search is full text over subject, preview text and sender address. Quoted phrases, OR and -exclude all work.

Conversations without fetching them

Pass latestOfThread=true to get one email per conversation. That gives you a conversation-style view at the cost of an ordinary list.
Your other filters are applied first, and the newest email that survives them is the one you get back. So this returns the last message each contact sent you – including in conversations you have already answered, where the newest message in the thread is your own reply:
An email that belongs to no conversation is a conversation of one, and is always kept. To open one conversation, list its messages with ?threadId=....

Read one email

GET /v1/emails/{id} is the only endpoint that returns the body.
It returns the same object as the list, plus:

Reply and forward

POST /v1/emails/{id}/reply answers in the conversation the email belongs to. You supply the body; the sender and the recipient are decided for you. The reply goes out from the mailbox that owns the conversation and is addressed to the other party, so a reply can never turn into a message to someone else.
Response
POST /v1/emails/{id}/forward sends the message on to recipients you choose, with the original quoted below your note. It also goes out from the mailbox that owns the conversation.

Recipients you add are checked against your blocklist

Anyone you name yourself – cc and bcc on a reply, to, cc and bcc on a forward – is checked against your workspace blocklist. If one of them is on it, the whole request is refused with 400 and nothing is sent; the message names every blocked address, so you can fix the list in one pass.

Read state

isUnread on an email means “this message arrived after the last time its conversation was read”. A conversation can therefore hold both read and unread messages at once, which is exactly what you want when polling: it tells you which replies are new, not merely which conversations have something new in them. You read that state per email, and you clear it per conversation. POST /v1/threads/{id}/read marks every email in a conversation as read. It is the only write there is for read state, and it is the same action a person takes by opening the conversation in the dashboard, so what you do through the API and what your team sees stay in step.

Delete an email

DELETE /v1/emails/{id} removes an email from your inbox. It stops appearing in listings. The copy on the mail server is left alone.