Skip to content

Write a reply now and send it later

POST
/v1/scheduled-messages
curl --request POST \
--url https://api.threadkite.app/v1/scheduled-messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "threadId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "channel": "email", "subject": "example", "text": "example", "html": "example", "cc": [ { "address": "accounts@example.co.uk", "name": "example" } ], "bcc": [ { "address": "accounts@example.co.uk", "name": "example" } ], "attachmentIds": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "channelAccountId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "mailboxConnectionId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "template": { "templateId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "variables": [] }, "signature": true, "sendAt": "2026-04-15T12:00:00Z", "cancelOnReply": true }'

Sent as you at sendAt (2 minutes to 60 days ahead), through the normal send, so consent and the channel are checked then. With cancelOnReply (the default) it is cancelled if the contact writes first. Needs a signed-in person.

Media typeapplication/json
object
threadId
required
string format: uuid
channel
required
string
Allowed values: email sms whatsapp chat marketplace messenger instagram
subject
string
nullable <= 500 characters
text
required
string
>= 1 characters <= 50000 characters
html
string
nullable <= 500000 characters
cc
Array<object>
<= 20 items
object
address
required
string
>= 3 characters <= 254 characters

Example

accounts@example.co.uk
name
string
nullable <= 200 characters
bcc
Array<object>
<= 20 items
object
address
required
string
>= 3 characters <= 254 characters

Example

accounts@example.co.uk
name
string
nullable <= 200 characters
attachmentIds

Files from POST /v1/attachments

Array<string>
<= 10 items
channelAccountId
string format: uuid
mailboxConnectionId
string format: uuid
template
object
templateId
required

From GET /v1/threads/{id}/reply-channels

string format: uuid
variables

Values for the template’s variables, in order

Array<string>
default: <= 20 items

Example

[
"Sarah"
]
signature

Email: add the signature when it is sent (on unless false)

boolean
sendAt
required

When to send it: at least 2 minutes and at most 60 days from now

string format: date-time
cancelOnReply

Cancel it if the contact writes before then

boolean
default: true
Media typeapplication/json
object
id
required
string format: uuid
threadId
required
string format: uuid
author
required
One of:
object
id
required
string
name
required
string
channel
required
string
Allowed values: email sms whatsapp chat marketplace messenger instagram
subject
required
string
nullable
text
required
string
html
required
string
nullable
attachmentCount
required

How many files are attached

number
usesTemplate
required

A WhatsApp template is used

boolean
sendAt
required
string format: date-time
cancelOnReply
required
boolean
status
required
string
Allowed values: pending sending sent cancelled failed
messageId
required

Once sent

string format: uuid
nullable
failureReason
required

Why it wasn’t sent, when it failed

string
nullable
cancelledReason
required
string
nullable
Allowed values: contact_replied cancelled
sentAt
required
string format: date-time
nullable
canEdit
required

You can change, send now or cancel it

boolean
createdAt
required
string format: date-time
updatedAt
required
string format: date-time

Example

{
"author": {
"id": "usr_8f2c",
"name": "James Patel"
},
"channel": "email",
"status": "pending",
"failureReason": "They have opted out of texts.",
"cancelledReason": "contact_replied"
}
Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

Missing or invalid API key

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

The organisation is on the Free plan (code upgrade_required)

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
feature
required

The feature that needs Pro

string
nullable
Allowed values: extraSeats connections aiAssistant aiReplies rules fullReports api inboxes bulkMessages videoMessages
upgradePath
required

Where to upgrade or pay, in the web app

string

Example

{
"statusCode": 402,
"code": "upgrade_required",
"message": "Connections are part of Pro. Upgrade to connect texts, calls and more.",
"feature": "extraSeats",
"upgradePath": "/settings/billing"
}

The key does not have the scope (or the person the permission)

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}
Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

Rate limit reached

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
retryAfter
required

Seconds until another request will be accepted

number

Example

{
"statusCode": 429,
"code": "rate_limited",
"message": "Too many requests. Each key can make 120 requests a minute; try again in 12 seconds.",
"retryAfter": 12
}