Skip to main content
POST
/
v1
/
chat
/
stream
Chat (Streaming)
curl --request POST \
  --url https://api.example.com/v1/chat/stream \
  --header 'Content-Type: application/json' \
  --data '
{
  "sessionId": "<string>",
  "message": "<string>"
}
'
{
  "type": "<string>",
  "conversationId": "<string>",
  "token": "<string>",
  "message": "<string>",
  "error": "<string>"
}

Endpoint

POST /v1/chat/stream
Legacy Endpoint: POST /chat is an alias for this endpoint and behaves identically. The widget uses /chat by default for backward compatibility.

Authentication

Requires one of the following headers:
  • x-api-key: Your widget API key
  • x-widget-api-key: Your widget API key (alternative)

Request Body

sessionId
string
required
Unique session identifier. Must match regex pattern ^[A-Za-z0-9._:-]{1,128}$.Used to track conversation history across multiple requests. Use the same sessionId for continuation of a conversation.
message
string
required
User’s chat message. Must be between 1 and 4000 characters.

Example Request Body

{
  "sessionId": "user-123",
  "message": "Explain what your company does"
}

Response

The response is streamed as NDJSON (Newline Delimited JSON) with Content-Type: application/x-ndjson. Each line is a JSON object representing a stream event.

Stream Event Types

Start Event

Sent at the beginning of the stream.
type
string
required
Event type: "start"
conversationId
string
required
Unique identifier for this conversation thread.
{"type":"start","conversationId":"j97ch2kj8xm6rpct8te5w9b1fh6pc7k8"}

Token Event

Sent for each token (word fragment) as the assistant generates the response.
type
string
required
Event type: "token"
token
string
required
A piece of the assistant’s response message.
{"type":"token","token":"We"}
{"type":"token","token":" are"}
{"type":"token","token":" a"}
{"type":"token","token":" customer"}
{"type":"token","token":" support"}

Done Event

Sent when the stream completes successfully.
type
string
required
Event type: "done"
message
string
required
The complete assistant response message.
conversationId
string
required
Unique identifier for this conversation thread.
{"type":"done","message":"We are a customer support platform that helps businesses engage with their customers.","conversationId":"j97ch2kj8xm6rpct8te5w9b1fh6pc7k8"}

Error Event

Sent when an error occurs during streaming.
type
string
required
Event type: "error"
error
string
required
Error message describing what went wrong.
{"type":"error","error":"Internal server error"}

Error Responses

400 Bad Request

Returned when request payload is invalid (before streaming starts).
{
  "error": "Invalid request payload"
}

401 Unauthorized

Returned when API key is missing or invalid.
{
  "error": "Unauthorized"
}

429 Too Many Requests

Returned when rate limit is exceeded.
{
  "error": "Too many requests"
}

500 Internal Server Error

Returned when an error occurs before streaming starts.
{
  "error": "Internal server error"
}
If an error occurs during streaming, an error event is sent in the NDJSON stream instead.

Example Requests

cURL
curl -X POST https://your-api-domain.com/v1/chat/stream \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key-here" \
  -d '{
    "sessionId": "user-123",
    "message": "Tell me about your services"
  }'
JavaScript
const response = await fetch('https://your-api-domain.com/v1/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'your-api-key-here'
  },
  body: JSON.stringify({
    sessionId: 'user-123',
    message: 'Tell me about your services'
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  
  const chunk = decoder.decode(value);
  const lines = chunk.split('\n').filter(line => line.trim());
  
  for (const line of lines) {
    const event = JSON.parse(line);
    
    switch (event.type) {
      case 'start':
        console.log('Stream started:', event.conversationId);
        break;
      case 'token':
        process.stdout.write(event.token);
        break;
      case 'done':
        console.log('\nComplete message:', event.message);
        break;
      case 'error':
        console.error('Error:', event.error);
        break;
    }
  }
}
Python
import requests
import json

response = requests.post(
    'https://your-api-domain.com/v1/chat/stream',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': 'your-api-key-here'
    },
    json={
        'sessionId': 'user-123',
        'message': 'Tell me about your services'
    },
    stream=True
)

for line in response.iter_lines():
    if line:
        event = json.loads(line)
        
        if event['type'] == 'start':
            print(f"Stream started: {event['conversationId']}")
        elif event['type'] == 'token':
            print(event['token'], end='', flush=True)
        elif event['type'] == 'done':
            print(f"\nComplete message: {event['message']}")
        elif event['type'] == 'error':
            print(f"Error: {event['error']}")

Rate Limiting

This endpoint is rate limited per client IP address. The limits are configured on the server side.

Notes

  • The response uses NDJSON format (Newline Delimited JSON)
  • Each line in the stream is a separate JSON object
  • The stream starts with a start event containing the conversationId
  • Token events are sent as the AI generates the response in real-time
  • The stream ends with a done event containing the full message
  • If an error occurs during streaming, an error event is sent
  • The conversation history is automatically maintained using the sessionId
  • Legacy endpoint /chat (POST) is also available with the same behavior

Build docs developers (and LLMs) love