Reading works with either credential; writing does not. Listing conversations and
paging message history accept your Org-API-Key (name the member with
externalUserID) or a member token. Sending a message and opening the SSE stream
are member-token only - a server cannot post as its own member.See Authentication for the two-token model and refresh contract.Stream live messages
Subscribe to new concierge messages over SSE, consumed as an
AsyncIterable,
AsyncStream, or Flow. The right way to receive incoming messages.Finding a conversation
You never create a conversation - they are created for you. Every member has a permanent concierge thread from the moment they exist, before they have redeemed anything, plus a dedicated thread per booking. So the only question is which id to use:type: "CONCIERGE" and titled with the experience; the permanent
thread is type: "GENERAL" with a null title, so label it yourself.
Pass either id to listMessages, sendMessage or the SSE stream.
conversationId on the redemption is available from 0.6.0. On earlier versions,
find a booking’s thread through listConversations instead.The flow
List the member’s conversations, read a thread’s history, then send a reply:Attachments
A concierge can send tickets, an itinerary or a photo. Those arrive as a message whoseattachments array is non-empty - and whose body is null, because a media message
carries no text.
Attachment[]
required
Always present. Empty for a text message, so you can map over it without a guard.
url can be null if a link could not be minted. That degrades one attachment; it never
fails the page of messages around it.
Attachments arrive over the SSE stream too, on the same message, so a live conversation
shows them without a refresh.
Sending attachments is not supported. Members send text; attachments are
concierge-to-member only.
Operations
List conversations
GET /v1/conversations returns the member’s conversations.
string
Names the member when a machine token calls on their behalf.
ListConversationsResponse:
Conversation[]
required
The member’s conversations.
List messages
GET /v1/conversations/{id}/messages returns one page of a conversation’s
messages with cursor pagination.
string
required
The conversation id.
integer
Page size. Defaults to the server’s default if omitted.
string
The
nextCursor from the previous page. Omit for the first page.string
Names the member when a machine token calls on their behalf.
ListMessagesResponse:
Message[]
required
The page of messages.
string | null
required
Pass this back as
cursor to fetch the next page. null marks the end of the
history.Send a message
POST /v1/conversations/{id}/messages posts a message to the conversation.
string
required
The conversation id.
string
required
The message text to send.
SendMessageResponse:
boolean
required
true when the message was accepted.Idempotency on
sendMessage is supported via the Idempotency-Key header- a retried send replays rather than double-posting. The API
reference omits the header on the
{id}route because of an emitter limitation, not because it is unsupported, so set the header yourself when retrying. The SDKs send one automatically on every write. See Retries and idempotency.
Schemas
Conversation
Message
Knowing when a message arrives
Three ways, with genuinely different latency. Pick by where your code runs.
In an app, use the stream. It relays new messages as they are written, and it is
the only option that is genuinely live.
On a backend, use the webhook. The stream needs a member token, so a server cannot
hold one on a member’s behalf. The webhook is how your backend learns our concierge has
replied - to send a push notification, or to mirror the thread into your CRM. See
Webhooks.
Testing in the sandbox
In the sandbox, the concierge is fully self-contained: a message you send is never forwarded to our Ops team, and a sandbox concierge bot replies automatically. The bot’s reply streams back to you overGET /v1/conversations/{id}/stream exactly like a real concierge message, so you
can build and test the whole send -> stream -> reply loop end to end without paging
a human. In LIVE, messages reach a real concierge as usual.
Related
Streaming messages
Receive live incoming messages over SSE.
Errors
The error taxonomy and stable codes for failed calls.