Skip to main content
POST
/
api
/
threads
/
{id}
/
messages
Send Message
curl --request POST \
  --url https://app.puffle.ai/api/threads/{id}/messages \
  --header 'Authorization: Bearer <token>'
CLI:
puffle thread message send --id <id>

Overview

Sends a message in an existing Unibox thread. For a new one-off email, first call Create thread, then call this endpoint with threading_mode: "new_thread". For an existing email or LinkedIn conversation, call this endpoint on the existing thread to reply from the connected sender.

Path Parameters

ParameterTypeDescription
idstringThread ID returned by POST /api/threads or any thread listing endpoint.

Request Body

FieldTypeRequiredDescription
body_textstringYesPlain-text message body. Empty strings are rejected.
body_htmlstringOptionalHTML body. For email, if omitted, Puffle derives HTML from body_text.
subjectstringRequired for new email threads unless the thread already has a subjectEmail subject. Ignored by LinkedIn sends.
account_idstringRequired for email when the thread has no senderEmail sender account ID. The account must belong to the workspace and be ready to send.
threading_mode"new_thread" or "reply"OptionalEmail threading behavior. Use "new_thread" for a one-off outbound email. If omitted, Puffle replies to the most recent inbound email when possible.
ccstringOptionalComma-separated CC recipients for email.
bccstringOptionalComma-separated BCC recipients for email.
attachmentsarrayOptionalAttachment metadata from the thread attachment upload endpoint.

Send a One-Off Email

curl -X POST "https://app.puffle.ai/api/threads/3d986dd1-9d70-45b7-8e36-5d5b8b1c9337/messages" \
  -H "Authorization: Bearer $PUFFLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "8a2f0c7a-9d1e-4d8f-9d7d-6a8b8e8f4a11",
    "subject": "Quick question",
    "body_text": "Hi Alex, I had a quick question about your outbound workflow.",
    "threading_mode": "new_thread"
  }'
On success, the response includes the saved outbound message and the refreshed thread. A one-off outbound email appears in Unibox with thread.inbox_state set to sent_one_off.
{
  "message": {
    "id": "6d54211c-7e24-4eb9-85fc-7388c8d89f2f",
    "conversation_id": "3d986dd1-9d70-45b7-8e36-5d5b8b1c9337",
    "direction": "outbound",
    "subject": "Quick question",
    "body_text": "Hi Alex, I had a quick question about your outbound workflow."
  },
  "thread": {
    "id": "3d986dd1-9d70-45b7-8e36-5d5b8b1c9337",
    "channel": "email",
    "status": "active",
    "inbox_state": "sent_one_off",
    "outbound_message_count": 1,
    "has_one_off_message": true
  }
}

Error Notes

StatusWhen it happens
400body_text is missing or empty, threading_mode is invalid, or attachment metadata is invalid.
404The thread does not exist or does not belong to the workspace.
422The thread cannot send on the requested channel, the recipient email is missing, or the sender account is not ready.
429The email provider rate-limited the send.
500The message may have been sent externally but failed to save locally. If the response says the message was sent but could not be saved, do not retry; the recipient may already have received it.
502The provider failed to send the message.

AI agent notes

For a brand-new one-off email, create the thread first and send with threading_mode: "new_thread". Do not retry a 500 response that says the message was sent but could not be saved, because the recipient may already have received it.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

id
string
required

Thread (conversations.id) UUID.

Response

Successful response.