Skip to main content
POST
/
api
/
threads
/
[id]
/
send
Send Thread Reply
curl --request POST \
  --url 'https://api.example.com/api/threads/[id]/send'
{
  "ok": true,
  "gmailMessageId": {},
  "error": "<string>"
}
Sends a reply email for a thread using the associated draft content. The message is sent via Gmail API and recorded in the database.

Authentication

Requires active session with elevated permissions. Permission Level: send or admin required

Path Parameters

id
string
required
The unique identifier of the thread to send a reply for

Request Body

No request body required. The endpoint uses the existing draft content stored in the database.

Response

Returns a success confirmation with the Gmail message ID.
ok
boolean
Always true when the send operation succeeds
gmailMessageId
string | null
The Gmail message ID returned by the Gmail API, or null if not available

Error Responses

error
string
Error message describing what went wrong
Status 401: User is not authenticated Status 403: User lacks required permissions (needs send or admin)
{
  "error": "Insufficient permissions"
}
Status 404: Thread not found
{
  "error": "thread not found"
}
Status 404: Service account not found
{
  "error": "service account not found"
}
Status 400: Gmail account not connected
{
  "error": "service gmail not connected"
}
Status 400: Draft is empty (no content after HTML stripping)
{
  "error": "draft is empty"
}
Status 409: Message already sent (draft was previously sent and not modified)
{
  "error": "already_sent"
}
Status 409: Duplicate send blocked (identical message sent within last 90 seconds)
{
  "error": "duplicate_send_blocked"
}

Behavior

Draft Usage

  • Uses the draft content and subject stored in the drafts table for the thread
  • If no draft exists, sends an empty message (which will fail validation)
  • Draft subject defaults to Re: {original subject} if not explicitly set

Duplicate Prevention

  • Checks if an identical outbound message was sent in the last 90 seconds
  • Comparison is done on HTML-stripped content
  • Returns 409 duplicate_send_blocked if duplicate detected

Database Updates

The send operation atomically:
  1. Updates thread status to sent and marks as read
  2. Updates or creates draft record with status: 'sent' and sentAt timestamp
  3. Inserts a new email record with direction: 'outbound'

Gmail Integration

  • Sends message as HTML MIME email via Gmail API
  • Preserves thread continuity using Gmail thread ID
  • Uses service account’s email address as sender

Examples

curl -X POST 'https://app.delightbridge.com/api/threads/thread_abc123/send' \
  -H 'Cookie: session=...'

Response Example

{
  "ok": true,
  "gmailMessageId": "18d4f5c6a8b2e9f1"
}

Notes

  • This endpoint requires send or admin permission level, unlike other thread endpoints which allow view or edit
  • The draft must have non-empty content (after HTML stripping) to be sent
  • Sends are idempotent: if a draft hasn’t been modified since being sent, re-sending returns already_sent error
  • Duplicate detection prevents accidental double-sends within a 90-second window
  • The message is sent from the service account’s email address to the thread’s customerEmail
  • All database operations (thread update, draft update, email insert) happen in a transaction

Build docs developers (and LLMs) love