Skip to main content
POST
/
api
/
v1
/
bookings
curl --request POST \
  --url https://chat.trysetter.com/api/v1/bookings \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "bot_id": 700,
  "phone": "+447813194799",
  "start_time": "2026-05-25T14:00:00Z",
  "end_time": "2026-05-25T15:00:00Z",
  "time_zone": "Europe/London",
  "source": "calendly",
  "external_id": "calendly-invitee-abc"
}
'
{
  "id": 555,
  "event_id": 999,
  "bot_id": 700,
  "contact_id": 42,
  "source": "calendly",
  "external_id": "calendly-invitee-abc",
  "start_time": "2026-05-25T14:00:00.000Z",
  "end_time": null,
  "time_zone": "Europe/London",
  "deduplicated": true
}

Documentation Index

Fetch the complete documentation index at: https://docs.trysetter.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This endpoint records an appointment that was booked outside of Setter (e.g. directly on your Calendly, a manual phone callback, or any other calendar tool). Once a booking is stored against a contact, the bot will see it on the next inbound message and will not ask the contact to book another appointment or send a booking link.
Authentication: All requests require a Bearer token in the Authorization header.

Contact Identification

You must provide either phone or wa_id to locate the contact. The contact must already exist in Setter — bookings cannot create new contacts. Lookup order:
  1. Exact wa_id match (if wa_id is supplied)
  2. wa_id derived from phone (E.164 minus the leading +)
  3. sms_phone_number match (both with and without leading +)
If both phone and wa_id are provided, wa_id is tried first. Pass default_country (ISO 3166-1 alpha-2) to disambiguate national-format phone numbers.

Bot Scope

A booking is only visible to the bot_id it was filed against. A bot that runs on multiple channels (e.g. WhatsApp + SMS) sees the same booking on both channels, but a separate bot owned by the same organization will not. Find the bot_id in the dashboard URL.

Idempotency

If external_id is provided, the unique key (organization_id, source, external_id) makes retries safe. A re-POST with the same triple returns the existing booking with deduplicated: true and HTTP 200 instead of creating a duplicate.

Important Notes

  • Authentication: All requests require a Bearer token in the Authorization header
  • Phone Format: Accepted with or without leading + and separators (parsed via libphonenumber)
  • Bot Visibility: Bookings are scoped to the bot_id they were filed against
  • Soft Cancellation: Use Cancel Booking to remove a booking from the bot’s context
  • Time Zone: Pass an IANA time_zone (e.g. Europe/London) for correct rendering in the bot’s context

Getting Your API Key

API keys can be generated from your Setter AI dashboard under Settings > API Keys. Keep your API key secure and never expose it in client-side code.

Example Usage

Create by phone number

curl -X POST https://chat.trysetter.com/api/v1/bookings \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": 700,
    "phone": "+447813194799",
    "start_time": "2026-05-25T14:00:00Z",
    "end_time": "2026-05-25T15:00:00Z",
    "time_zone": "Europe/London",
    "source": "calendly",
    "external_id": "calendly-invitee-abc"
  }'

Create by WhatsApp ID

curl -X POST https://chat.trysetter.com/api/v1/bookings \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": 700,
    "wa_id": "447813194799",
    "start_time": "2026-05-25T14:00:00Z",
    "time_zone": "Europe/London",
    "source": "manual"
  }'

Authorizations

Authorization
string
header
required

Bearer token authentication using your API key

Body

application/json
bot_id
integer
required

The bot this booking is for. Find the id in the dashboard URL.

Example:

700

start_time
string<date-time>
required

ISO 8601 timestamp of the appointment start.

Example:

"2026-05-25T14:00:00Z"

phone
string

Contact's phone number. Accepted with or without leading + and separators (parsed via libphonenumber). Provide either phone or wa_id.

Example:

"+447813194799"

wa_id
string

WhatsApp ID of the contact. Use this instead of phone if you have it. If both are provided, wa_id is tried first.

Example:

"447813194799"

end_time
string<date-time>

ISO 8601 timestamp of the appointment end. Must be after start_time.

Example:

"2026-05-25T15:00:00Z"

time_zone
string

IANA time zone (e.g. Europe/London).

Example:

"Europe/London"

source
string

Free-form provenance tag. Defaults to manual.

Example:

"calendly"

external_id
string

Stable id from your system used to deduplicate retries. Unique key is (organization_id, source, external_id).

Example:

"calendly-invitee-abc"

default_country
string

ISO 3166-1 alpha-2 country code (e.g. GB). Used to disambiguate national-format phone numbers.

Example:

"GB"

metadata
object

Arbitrary JSON stored alongside the booking.

Example:
{
"invitee_email": "lead@example.com",
"calendly_event_uri": "https://api.calendly.com/scheduled_events/abc"
}

Response

Idempotent replay — a booking with the same (organization_id, source, external_id) already existed and is returned with deduplicated: true.

id
integer
Example:

555

event_id
integer
Example:

999

bot_id
integer
Example:

700

contact_id
integer
Example:

42

source
string
Example:

"calendly"

external_id
string | null
Example:

"calendly-invitee-abc"

start_time
string<date-time>
Example:

"2026-05-25T14:00:00.000Z"

end_time
string<date-time> | null
Example:

"2026-05-25T15:00:00.000Z"

time_zone
string | null
Example:

"Europe/London"

deduplicated
boolean

true when an external_id collision returned the existing record instead of creating a new one.

Example:

false