Real-time messaging API for the Freeday webchat, powered by Centrifugo. REST endpoints and the conversation data export are documented alongside this protocol on docs.freeday.ai.
| Service | URL |
|---|---|
| REST API | https://api.freeday.ai |
| WebSocket | wss://realtime.freeday.ai |
All REST calls require the X-Company header (from Settings → Company in the Freeday platform). After the first call, they also require the X-Session-Id header.
The server issues the session ID. Do not generate one yourself. Send the first call without X-Session-Id, store the X-Session-Id header from its response, and send that ID on every later call. A session expires after 30 days without activity. A call with an expired or unknown session ID gets 403 with error code session_invalid. Then delete the stored session ID and conversation ID, and create a new conversation without X-Session-Id to get a new session. The new session cannot use the conversations of the expired one.
wss://realtime.freeday.ai/connection/websocket with the token. See Centrifugo client SDK docs.channel from step 4 with a getToken callback.Example (centrifuge-js):
const sub = client.newSubscription(channel, {
getToken: async () => {
const res = await fetch("https://api.freeday.ai/sdk/v1/auth/subscribe-token", {
method: "POST",
headers: { "Content-Type": "application/json", "X-Session-Id": sessionId, "X-Company": companyId },
body: JSON.stringify({ conversation_id: conversationId }),
});
return (await res.json()).subscription_token;
},
});
sub.on("publication", (ctx) => handleEnvelope(ctx.data));
sub.subscribe();
Sending: Publish a SendMessage via subscription.publish().
Receiving: The server streams MessageEnvelope objects. Envelopes carry a sequence number — discard out-of-order envelopes. Ignore envelopes with an unrecognized proto version.
Streaming example:
{ operation: "replace", sequence: 1, message_snapshot: { status: "partial", blocks: [{ id: "b1", type: "typing", typing: true }] } }{ operation: "replace", sequence: 2, message_snapshot: { status: "partial", blocks: [{ id: "b2", type: "markdown", content: "Hello! I can" }] } }{ operation: "complete", sequence: 3, message_snapshot: { status: "complete", blocks: [{ id: "b2", type: "markdown", content: "Hello! I can help you with that." }] } }Production Centrifugo server
JWT tokens are used for both connection and channel subscription authentication.
POST /sdk/v1/auth/connect-token (15 min expiry)POST /sdk/v1/auth/subscribe-token (24 hour expiry)Real-time message channel for a specific conversation.
Clients subscribe to receive messages from the digital employee, agents, and system. Clients publish to send user messages.
History: 100 messages retained for 1 hour. See the Centrifugo history documentation for retrieval details.
Receive a message envelope from the server
The server sends MessageEnvelope objects containing the message state and an operation
that tells the client how to process it. Messages stream in via replace → … → complete.
Available only on servers:
UUID of the company
UUID of the conversation
Accepts the following message:
Server-to-client message wrapper with streaming semantics
Wrapper around a message with streaming/sequencing metadata
{
"proto": 1,
"kind": "message",
"operation": "replace",
"sequence": 0,
"message_snapshot": {
"message_id": "d7d9d9fd-478f-40e6-b651-49b7f19878a2",
"participant_from": {
"role": "digital_employee",
"name": "string"
},
"interaction_id": "fd463a24-cab4-49e4-b915-3c70a62977c3",
"channel_id_from": "string",
"sent_at": "2019-08-24T14:15:22Z",
"conversation_id": "cc71b11a-25cd-4c2d-9950-df2cc38e3407",
"blocks": [
{
"id": "string",
"type": "text",
"text": "string"
}
],
"status": "partial",
"trace_id": "string",
"request_user_feedback": true,
"user_feedback_value": "string",
"provenance": {
"manifest_id": "82825e8e-31fc-47d5-83ce-cd926068341e",
"manifest_url": "http://example.com",
"ai_origin": "ai_generated"
}
},
"timestamp": "2019-08-24T14:15:22Z",
"error": "string"
}
Real-time message channel for a specific conversation.
Clients subscribe to receive messages from the digital employee, agents, and system. Clients publish to send user messages.
History: 100 messages retained for 1 hour. See the Centrifugo history documentation for retrieval details.
Send a user message
Publish a user message via subscription.publish().
Available only on servers:
UUID of the company
UUID of the conversation
Accepts the following message:
User message (client-to-server)
A message sent from the client to the server. Fields like status and trace_id
are server-managed and should not be included.
Simple text message
{
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"participant_from": {
"role": "user",
"name": ""
},
"blocks": [
{
"id": "block-1",
"type": "text",
"text": "Hello, I need help with my booking"
}
],
"interaction_id": "660e8400-e29b-41d4-a716-446655440000",
"channel_id_from": "de-123",
"sent_at": "2025-01-15T10:30:00Z",
"conversation_id": "770e8400-e29b-41d4-a716-446655440000"
}
Text message with an attached image
{
"message_id": "550e8400-e29b-41d4-a716-446655440001",
"participant_from": {
"role": "user",
"name": ""
},
"blocks": [
{
"id": "block-1",
"type": "text",
"text": "Is this the right part?"
},
{
"id": "block-2",
"type": "image_reference",
"url": "https://storage.googleapis.com/chat-attachments/9f1c0b3e-7a42-4d10-9c5e-2b8f6d4a1e33.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=604800&X-Goog-Signature=...",
"filename": "9f1c0b3e-7a42-4d10-9c5e-2b8f6d4a1e33.jpg"
}
],
"interaction_id": "660e8400-e29b-41d4-a716-446655440001",
"channel_id_from": "de-123",
"sent_at": "2025-01-15T10:31:00Z",
"conversation_id": "770e8400-e29b-41d4-a716-446655440000"
}
Server-to-client message wrapper with streaming semantics
Wrapper around a message with streaming/sequencing metadata
User message (client-to-server)
A message sent from the client to the server. Fields like status and trace_id
are server-managed and should not be included.
Wrapper around a message with streaming/sequencing metadata
Controls how the client should process the message
Common fields shared by client-sent and server-delivered messages
A message sent from the client to the server. Fields like status and trace_id
are server-managed and should not be included.
A full chat message as delivered by the server inside a MessageEnvelope.
Contains both client-provided and server-managed fields.
Who wrote the message text
Current processing state of the message
Content block within a message. Additional block types may be introduced in future versions.
An image, referenced by URL rather than embedded in the message.
You can point url at any image the end user's browser can reach.
Freeday-hosted URLs expire seven days after upload. Treat the url on an older
message as potentially dead — an image replayed from channel history more than a week
after it was sent will no longer load. Upload the image again to get a working link.