Security, Privacy, AI and CSR information for all Piano products now lives in one place. Explore our Compliance Center.
Audience
English French
English French

/ai/segment/*chat | stream

API call to create, refine, and delete audience segments through AI-powered multi-turn conversation. The endpoint supports streaming (SSE) for real-time progress updates during segment generation.

Within a conversation the assistant can create segments, update them, and delete them. Updates and deletions are restricted to segments that were created earlier in the same conversation via create_segment; requests to change any other segment are rejected. An update only changes the fields the assistant supplies, so a rename leaves the filters untouched.

The user must be authenticated and have both read and write permissions to the siteGroup, because the assistant creates and deletes segments on their behalf. The customer must have the AI feature enabled. Both endpoints enforce this.

Endpoints

Path

Transport

Description

/ai/segment/chat

JSON (POST)

Non-streaming request/response

/ai/segment/chat/stream

SSE (POST)

Streaming with real-time progress events

The streaming endpoint returns Server-Sent Events (SSE) with progress updates as the AI processes the request, while the non-streaming endpoint returns a single JSON response. The streaming endpoint only supports start and message operations, while the non-streaming endpoint supports all five operations.

Request

Non-streaming endpoint (/ai/segment/chat)

Name

Type

Required

Description

operation

String

Yes

The chat operation to perform. One of: start, message, list, history, end

siteGroupId

String

Yes

The site group identifier to scope the conversation to

conversationId

String

Depends

The conversation identifier. Required for message, history, and end operations

message

String

Depends

The user's message text. Required for start and message operations. Must be non-empty

userId

String

No

Optional user identifier to associate with the conversation. Only used on start

includeHistory

boolean

No

Whether to include conversation history in the response. Defaults to true. Only for start and message

maxHistoryMessages

Integer

No

Limit the number of history messages returned. Returns most recent N messages. No limit by default

Streaming endpoint (/ai/segment/chat/stream)

Name

Type

Required

Description

operation

String

Yes

The chat operation to perform. Only start and message are supported

siteGroupId

String

Yes

The site group identifier to scope the conversation to

conversationId

String

Depends

The conversation identifier. Required for message operation

message

String

Yes

The user's message text. Must be non-empty

userId

String

No

Optional user identifier to associate with the conversation. Only used on start

The conversation is always scoped to the authenticated caller, so conversations started here are visible to the list and history operations of the non-streaming endpoint.

On a message operation the site group of the existing conversation is used, so a siteGroupId that differs from the one the conversation was started with is ignored rather than honoured.

Operations

start - Start a New Conversation Begins a new AI segment chat conversation with an initial message. The AI will analyze the request, fetch relevant data from the site group, and generate a segment definition. Supported by both endpoints.

message - Send a Follow-up Message Sends a follow-up message in an existing conversation. The AI maintains context from previous messages and can refine or modify previously generated segments. Supported by both endpoints.

list - List Conversations Lists all conversations for the authenticated user, filtered by site group. Returns a summary of each conversation including the first message and creation time. Non-streaming endpoint only.

history - Get Conversation History Retrieves the full message history for an existing conversation. Non-streaming endpoint only.

end - End a Conversation Ends and cleans up a conversation. The conversation data is given a short TTL (approximately 1 hour) after which it expires. Until then the conversation is still returned by list, flagged with ended: true, and can still be read with history. Non-streaming endpoint only.

Active conversations are retained for 90 days by default. Ended conversations expire about 1 hour after the end operation.

Response

Non-streaming response (/ai/segment/chat)

For start and message operations

Name

Type

Description

conversationId

String

Unique identifier for the conversation

responseText

Object

The generated segment definition as a JSON object

conversationHistory

Array of object

List of chat messages (empty if includeHistory is false)

success

boolean

Whether the operation succeeded

error

String

Error message if the operation failed

For list operation

Name

Type

Description

conversations

Array of object

Array of conversation summary objects

A conversation summary object has the following fields:

Name

Type

Description

conversationId

String

Unique identifier for the conversation

siteGroupId

String

The site group identifier

createdAt

Number

Unix timestamp in milliseconds when the conversation started

firstMessage

String

Preview of the first message (truncated to 100 characters)

ended

boolean

Whether the conversation has been ended; ended conversations stop being listed once they expire

For history operation

Name

Type

Description

messages

Array of object

Array of chat messages

For end operation

Name

Type

Description

success

boolean

Whether the conversation was ended

Chat message object

Messages in conversationHistory and messages arrays have the following fields:

Name

Type

Description

role

String

"user" or "assistant"

content

String

The message text

timestamp

Number

Unix timestamp in milliseconds

segmentJson

Object/null

Parsed segment definition JSON, if the message contains one

Streaming response (/ai/segment/chat/stream)

The streaming endpoint returns Server-Sent Events. Each event is a JSON object with an eventType field:

eventType

Description

Key fields

thinking

The AI is analyzing the request

message

tool_call

The AI is fetching data or performing a segment action (e.g. create_segment, update_segment, delete_segment, restore_segment)

toolName, toolUseId, toolArgs, message

tool_result

A tool invocation completed. success is false when the tool failed, and error then says why

toolName, toolUseId, segmentId, message, success, error

complete

The segment has been generated

conversationId, responseText, conversationHistory, success

error

An error occurred

message, success

Segment response object

The responseText field contains the generated segment definition:

Name

Type

Description

name

String

Name of the generated segment

description

String

Description of the generated segment

inferred

String

The inferred segment type: traffic or lookalike

filters

Array of object

Segment filter definitions. See Traffic filters for syntax

chat_message

String

A conversational summary of what was created or changed

Examples

Start a conversation (non-streaming)

Bash
$ python cx.py /ai/segment/chat '{"operation": "start", "siteGroupId": "1135172335968227720", "message": "Create a segment for users from Chicago on Safari who read Robert Herguth articles"}'
{
 "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19",
 "responseText": {
 "name": "Chicago Safari Users Reading Robert Herguth",
 "description": "Users from Chicago using Safari browser who read articles by Robert Herguth",
 "inferred": "traffic",
 "filters": [
 {
 "type": "time",
 "start": "-30d",
 "filter": {
 "type": "user",
 "having": {
 "min": 1,
 "filter": {
 "type": "and",
 "filters": [
 {
 "type": "event",
 "group": "city",
 "items": ["chicago"]
 },
 {
 "type": "event",
 "group": "browser",
 "items": ["Safari"]
 },
 {
 "type": "keyword",
 "group": "author",
 "items": ["robert herguth"]
 }
 ]
 }
 }
 }
 }
 ],
 "chat_message": "Created your segment targeting Chicago users on Safari who read Robert Herguth articles. Would you like to adjust anything?"
 },
 "conversationHistory": [
 {
 "role": "user",
 "content": "Create a segment for users from Chicago on Safari who read Robert Herguth articles",
 "timestamp": 1709654400000,
 "segmentJson": null
 },
 {
 "role": "assistant",
 "content": "Created your segment targeting Chicago users on Safari who read Robert Herguth articles. Would you like to adjust anything?",
 "timestamp": 1709654415000,
 "segmentJson": { "..." }
 }
 ],
 "success": true,
 "error": null
}

Send a follow-up message

Bash
$ python cx.py /ai/segment/chat '{"operation": "message", "siteGroupId": "1135172335968227720", "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19", "message": "Exclude users from Norway"}'
{
 "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19",
 "responseText": {
 "name": "Chicago Safari Users Reading Robert Herguth (Excluding Norway)",
 "description": "Users from Chicago using Safari browser who read articles by Robert Herguth, excluding users from Norway",
 "inferred": "traffic",
 "filters": ["..."],
 "chat_message": "Updated your segment to exclude Norwegian users. Any other adjustments needed?"
 },
 "conversationHistory": ["..."],
 "success": true,
 "error": null
}

List conversations

Bash
$ python cx.py /ai/segment/chat '{"operation": "list", "siteGroupId": "1135172335968227720"}'
{
 "conversations": [
 {
 "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19",
 "siteGroupId": "1135172335968227720",
 "createdAt": 1709654400000,
 "firstMessage": "Create a segment for users from Chicago on Safari who read Robert Herguth articles",
 "ended": false
 }
 ]
}

Get conversation history

Bash
$ python cx.py /ai/segment/chat '{"operation": "history", "siteGroupId": "1135172335968227720", "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19"}'
{
 "messages": [
 {
 "role": "user",
 "content": "Create a segment for users from Chicago on Safari who read Robert Herguth articles",
 "timestamp": 1709654400000,
 "segmentJson": null
 },
 {
 "role": "assistant",
 "content": "Created your segment targeting Chicago users on Safari who read Robert Herguth articles. Would you like to adjust anything?",
 "timestamp": 1709654415000,
 "segmentJson": { "..." }
 }
 ]
}

End a conversation

Bash
$ python cx.py /ai/segment/chat '{"operation": "end", "siteGroupId": "1135172335968227720", "conversationId": "e70245d5-0c6e-4dd9-a455-3f02b8de9c19"}'
{
 "success": true
}

Streaming example (SSE events)

Bash
$ python cx.py /ai/segment/chat/stream '{"operation": "start", "siteGroupId": "1135172335968227720", "message": "Create a segment for sports fans"}'
data: {
 "conversationId": "abc-123",
 "eventType": "thinking",
 "message": "Analyzing request..."
}

data: {
 "eventType": "tool_call",
 "toolName": "list_keyword_groups",
 "message": "Discovering keyword groups..."
}

data: {
 "eventType": "tool_result",
 "toolName": "list_keyword_groups",
 "message": "Discovering keyword groups done"
}

data: {
 "eventType": "tool_call",
 "toolName": "get_keyword_items",
 "message": "Fetching keyword data..."
}

data: {
 "eventType": "tool_result",
 "toolName": "get_keyword_items",
 "message": "Fetching keyword data done"
}

data: {
 "eventType": "tool_call",
 "toolName": "create_segment",
 "message": "Creating segment..."
}

data: {
 "eventType": "tool_result",
 "toolName": "create_segment",
 "toolUseId": "toolu_01A09q90qw90lq917835lq9",
 "segmentId": "1y2ir0osde3ep",
 "message": "Creating segment done",
 "success": true
}

data: {
 "conversationId": "abc-123",
 "eventType": "complete",
 "responseText": {...},
 "conversationHistory": [...],
 "success": true
}

Error Responses

Non-streaming endpoint (/ai/segment/chat)

Condition

HTTP Status

Error message

Missing siteGroupId

400

siteGroupId parameter is required

Missing operation

400

operation parameter is required

Missing conversationId

400

conversationId parameter is required

Empty message

400

message is required

Unknown operation

400

Unknown chat operation: <operation>

No AI feature, or no read/write permission on the siteGroup

403

Permission denied

No access to the conversation, or the conversation has expired

200

{"error": "Permission denied"}

Service unavailable

200

{"error": "AI segment chat service is not available"}

An unknown, expired or someone else's conversation are all answered with Permission denied, so that the response does not reveal whether a given conversation id exists.

Streaming endpoint (/ai/segment/chat/stream)

Validation errors are returned as SSE events with eventType: "error" rather than HTTP error codes:

Condition

Error message

Missing siteGroupId or operation

HTTP 400: siteGroupId and operation are required

Invalid JSON request

HTTP 400: Invalid JSON request

Missing conversationId

SSE: {"eventType":"error","message":"conversationId is required"}

Empty message

SSE: {"eventType":"error","message":"message is required"}

Not authenticated, or no AI feature

HTTP 403: Permission denied (sent before the event stream opens)

No access to the conversation, or the conversation has expired

SSE: {"eventType":"error","message":"Permission denied","success":false}

Unsupported operation

SSE: {"eventType":"error","message":"Streaming only supports 'start' and 'message' operations"}

Internal error

SSE: {"eventType":"error","message":"An internal error occurred. Please try again.","success":false}

Matching results to calls

toolUseId identifies one tool call and is repeated on its tool_result, so a turn that makes several calls to the same tool can be followed without assuming the events arrive in order. A turn that acts on three segments makes three calls, each of which succeeds or fails on its own, so per-call results are the normal case rather than the exception.

segmentId on a tool_result is the segment the call acted on: the id a create produced, the id an update or a delete was given, or the id a restore ended up with — a new one when the original could not be brought back. It is absent for tools that do not act on a segment. Read the id from here rather than from the assistant's text: the wording of that text comes from a prompt and can change at any time.

restore_segment undoes a delete_segment made in the same conversation. It brings the original segment back with the id it had, through /segment/restore, for a user who may restore — admins and customer admins. For anyone else, and for a segment /segment/restore can no longer rebuild, the definition the segment had when it was deleted is created again as a new segment with a new id.

A failing tool call is not one of these: it does not end the stream, because the model is told what went wrong and carries on. It is reported on the tool_result event instead, and the operation it stands for (a segment create, update or delete) did not happen:

data: {
 "eventType": "tool_result",
 "toolName": "create_segment",
 "message": "Creating segment failed",
 "success": false,
 "error": "'filters' must be a JSON array of filter objects, got string"
}

Last updated: