Skip to content

Book an appointment

POST
/v1/appointments
curl --request POST \
--url https://api.threadkite.app/v1/appointments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "threadId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "type": "consultation", "startsAt": "2026-04-15T12:00:00Z", "endsAt": "2026-04-15T12:00:00Z", "hostUserId": "example", "locationId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "itemId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "notes": "example", "notifyChannel": "email" }'

From a thread with a contact. With notifyChannel, the customer is sent a confirmation now (with a calendar file by email), reminders the day before and two hours before, and any changes. If their consent or details don’t allow it, the appointment is still booked and notifyFailure says why.

Media typeapplication/json
object
threadId
required

The thread it is booked from

string format: uuid
type
required

An id from GET /v1/appointment-types

string
>= 1 characters <= 60 characters

Example

consultation
startsAt
required
string format: date-time
endsAt

When it ends; defaults to the type’s usual length

string format: date-time
hostUserId

Who it is with (a Full seat who can see the thread). Defaults to you, else the thread owner.

string
>= 1 characters <= 100 characters
locationId

Where it is; defaults to the thread’s location

string format: uuid
nullable
itemId

What it is about; defaults to the thread’s item

string format: uuid
nullable
notes
string
nullable <= 2000 characters
notifyChannel

Send a confirmation, reminders (the day before and two hours before) and any changes on this channel. Null sends nothing.

string
nullable
Allowed values: email sms whatsapp
Media typeapplication/json
object
id
required
string format: uuid
threadId
required
string format: uuid
inboxId
required

The thread’s inbox

string format: uuid
contact
required
One of:
object
id
required
string format: uuid
name
required
string
nullable
type
required
string
typeLabel
required
string
startsAt
required
string format: date-time
endsAt
required
string format: date-time
timeZone
required

The time zone it is written in

string
status
required
string
Allowed values: booked confirmed cancelled no_show completed
host
required
One of:
object
id
required
string
name
required
string
locationId
required
string format: uuid
nullable
item
required
One of:
object
id
required
string format: uuid
title
required
string
notes
required
string
nullable
notifyChannel
required

The channel the customer is told on (null: not told)

string
nullable
Allowed values: email sms whatsapp
notifyFailure
required

Why the latest message to the customer wasn’t sent, if it wasn’t

string
nullable
cancelledReason
required

Why it was cancelled (for the team)

string
nullable
createdBy
required
One of:
object
id
required
string
name
required
string
canEdit
required

You can move, cancel and mark it

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

Example

{
"contact": {
"name": "Sarah Turner"
},
"type": "consultation",
"typeLabel": "Consultation",
"timeZone": "Europe/London",
"status": "booked",
"host": {
"id": "usr_8f2c",
"name": "James Patel"
},
"item": {
"title": "Oak dining table"
},
"notifyChannel": "email",
"notifyFailure": "They have opted out of texts.",
"createdBy": {
"id": "usr_8f2c",
"name": "James Patel"
}
}
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
}