Overview
The Playground API provides endpoints for managing chat sessions, sending messages, and retrieving observability data. All endpoints (except health) require JWT authentication.
Base URL
# Development
http://localhost:8002
# Test Infrastructure
http://localhost:9002
# Production
https://playground.yourdomain.com
Authentication
All endpoints except /api/playground/health require JWT authentication:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...
Health Endpoints
GET /api/playground/health
Health check endpoint (no authentication required).
Response :
{
"status" : "healthy" ,
"version" : "1.0.0" ,
"dependencies" : {
"redis" : "healthy" ,
"mcp_server" : "healthy"
}
}
Status Codes :
One or more dependencies are unhealthy {
"status" : "unhealthy" ,
"dependencies" : {
"redis" : "unhealthy" ,
"mcp_server" : "healthy"
}
}
Session Endpoints
POST /api/playground/sessions
Create a new chat session.
Display name for the session (optional)
Custom metadata to attach to the session (optional)
Request :
curl -X POST http://localhost:9002/api/playground/sessions \
-H "Authorization: Bearer $TOKEN " \
-H "Content-Type: application/json" \
-d '{
"name": "My Chat Session",
"metadata": {
"project": "demo"
}
}'
Response :
{
"session_id" : "sess_abc123def456" ,
"name" : "My Chat Session" ,
"user_id" : "alice" ,
"created_at" : "2025-12-06T10:00:00Z" ,
"updated_at" : "2025-12-06T10:00:00Z" ,
"metadata" : {
"project" : "demo"
}
}
Status Codes :
Session created successfully
Invalid or missing authentication token
GET /api/playground/sessions
List all sessions for the authenticated user.
Maximum number of sessions to return
Number of sessions to skip for pagination
Request :
curl http://localhost:9002/api/playground/sessions?limit= 10 \
-H "Authorization: Bearer $TOKEN "
Response :
[
{
"session_id" : "sess_abc123def456" ,
"name" : "My Chat Session" ,
"user_id" : "alice" ,
"created_at" : "2025-12-06T10:00:00Z" ,
"updated_at" : "2025-12-06T10:30:00Z" ,
"message_count" : 5
},
{
"session_id" : "sess_xyz789" ,
"name" : "Test Session" ,
"user_id" : "alice" ,
"created_at" : "2025-12-05T09:00:00Z" ,
"updated_at" : "2025-12-05T09:15:00Z" ,
"message_count" : 3
}
]
GET /api/playground/sessions/
Get details for a specific session including message history.
Path Parameters :
Request :
curl http://localhost:9002/api/playground/sessions/sess_abc123def456 \
-H "Authorization: Bearer $TOKEN "
Response :
{
"session_id" : "sess_abc123def456" ,
"name" : "My Chat Session" ,
"user_id" : "alice" ,
"created_at" : "2025-12-06T10:00:00Z" ,
"updated_at" : "2025-12-06T10:30:00Z" ,
"messages" : [
{
"id" : "msg_001" ,
"role" : "user" ,
"content" : "Hello, what can you help me with?" ,
"timestamp" : "2025-12-06T10:00:05Z"
},
{
"id" : "msg_002" ,
"role" : "assistant" ,
"content" : "I can help you with a variety of tasks..." ,
"timestamp" : "2025-12-06T10:00:08Z" ,
"tool_calls" : []
}
],
"metadata" : {
"model" : "gemini-2.5-flash" ,
"total_tokens" : 150
}
}
Status Codes :
Session retrieved successfully
Session does not exist or user lacks access
DELETE /api/playground/sessions/
Delete a session and all its messages.
Request :
curl -X DELETE http://localhost:9002/api/playground/sessions/sess_abc123def456 \
-H "Authorization: Bearer $TOKEN "
Response :
{
"message" : "Session deleted successfully"
}
Status Codes :
Session deleted successfully
Chat Endpoints
POST /api/playground/chat
Send a message and receive a response.
The session ID to send the message to
The user’s message content
Enable streaming response (SSE)
Request (Non-Streaming) :
curl -X POST http://localhost:9002/api/playground/chat \
-H "Authorization: Bearer $TOKEN " \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_abc123def456",
"message": "What is 2 + 2?"
}'
Response :
{
"message_id" : "msg_003" ,
"role" : "assistant" ,
"content" : "2 + 2 equals 4." ,
"timestamp" : "2025-12-06T10:30:05Z" ,
"tool_calls" : [],
"usage" : {
"prompt_tokens" : 25 ,
"completion_tokens" : 10 ,
"total_tokens" : 35
}
}
Request (Streaming) :
curl -X POST http://localhost:9002/api/playground/chat \
-H "Authorization: Bearer $TOKEN " \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"session_id": "sess_abc123def456",
"message": "Explain machine learning",
"stream": true
}'
Streaming Response (SSE) :
event: token
data: {"content": "Machine"}
event: token
data: {"content": " learning"}
event: token
data: {"content": " is"}
event: tool_call
data: {"name": "search", "args": {"query": "machine learning definition"}}
event: tool_result
data: {"content": "ML is a subset of AI..."}
event: end
data: {"usage": {"total_tokens": 150}}
Status Codes :
Message processed successfully
Observability Endpoints
GET /api/playground/observability/traces
Get OpenTelemetry traces for a session.
Filter traces by session ID
Maximum number of traces to return
Request :
curl "http://localhost:9002/api/playground/observability/traces?session_id=sess_abc123" \
-H "Authorization: Bearer $TOKEN "
Response :
[
{
"trace_id" : "abc123def456789" ,
"span_id" : "span_001" ,
"operation" : "chat.process" ,
"duration_ms" : 1250 ,
"status" : "OK" ,
"attributes" : {
"model" : "gemini-2.5-flash" ,
"tokens" : 150
},
"timestamp" : "2025-12-06T10:30:00Z"
}
]
GET /api/playground/observability/logs
Get structured logs for a session.
Filter logs by session ID
Minimum log level (DEBUG, INFO, WARN, ERROR)
Request :
curl "http://localhost:9002/api/playground/observability/logs?session_id=sess_abc123&level=INFO" \
-H "Authorization: Bearer $TOKEN "
Response :
[
{
"timestamp" : "2025-12-06T10:30:00Z" ,
"level" : "INFO" ,
"message" : "Processing chat message" ,
"attributes" : {
"session_id" : "sess_abc123" ,
"message_length" : 25
}
}
]
GET /api/playground/observability/metrics
Get metrics for a session.
Request :
curl "http://localhost:9002/api/playground/observability/metrics?session_id=sess_abc123" \
-H "Authorization: Bearer $TOKEN "
Response :
{
"session_id" : "sess_abc123" ,
"message_count" : 10 ,
"total_tokens" : 1500 ,
"average_latency_ms" : 850 ,
"error_count" : 0 ,
"tool_call_count" : 3
}
WebSocket API
WS /ws/playground/
Real-time bidirectional chat using WebSocket.
Connection :
const ws = new WebSocket ( 'ws://localhost:9002/ws/playground/sess_abc123' );
ws . onopen = () => {
// Authenticate
ws . send ( JSON . stringify ({
type: 'auth' ,
token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...'
}));
};
ws . onmessage = ( event ) => {
const data = JSON . parse ( event . data );
console . log ( 'Received:' , data );
};
Message Types :
Client Messages
Server Messages
// Authentication
{ "type" : "auth" , "token" : "eyJ..." }
// Send chat message
{ "type" : "chat" , "message" : "Hello!" }
// Cancel current response
{ "type" : "cancel" }
// Ping (keepalive)
{ "type" : "ping" }
// Authentication result
{ "type" : "auth_success" , "user_id" : "alice" }
{ "type" : "auth_error" , "message" : "Invalid token" }
// Streaming tokens
{ "type" : "token" , "content" : "Hello" }
// Tool calls
{ "type" : "tool_call" , "name" : "search" , "args" : { ... } }
{ "type" : "tool_result" , "content" : "..." }
// Completion
{ "type" : "end" , "usage" : { "total_tokens" : 100 } }
// Errors
{ "type" : "error" , "message" : "Processing failed" }
// Pong (keepalive response)
{ "type" : "pong" }
Example Session :
const ws = new WebSocket ( 'ws://localhost:9002/ws/playground/sess_abc123' );
ws . onopen = () => {
// Step 1: Authenticate
ws . send ( JSON . stringify ({ type: 'auth' , token: TOKEN }));
};
ws . onmessage = ( event ) => {
const msg = JSON . parse ( event . data );
switch ( msg . type ) {
case 'auth_success' :
// Step 2: Send chat message
ws . send ( JSON . stringify ({ type: 'chat' , message: 'Hello!' }));
break ;
case 'token' :
// Step 3: Handle streaming tokens
process . stdout . write ( msg . content );
break ;
case 'tool_call' :
console . log ( ` \n Tool: ${ msg . name } ( ${ JSON . stringify ( msg . args ) } )` );
break ;
case 'end' :
console . log ( ` \n Total tokens: ${ msg . usage . total_tokens } ` );
break ;
case 'error' :
console . error ( 'Error:' , msg . message );
break ;
}
};
Error Responses
All endpoints may return the following errors:
401 Unauthorized
{
"error" : "unauthorized" ,
"message" : "Invalid or expired token" ,
"code" : "AUTH_INVALID_TOKEN"
}
403 Forbidden
{
"error" : "forbidden" ,
"message" : "Access denied to this resource" ,
"code" : "AUTH_ACCESS_DENIED"
}
404 Not Found
{
"error" : "not_found" ,
"message" : "Session not found" ,
"code" : "SESSION_NOT_FOUND"
}
429 Too Many Requests
{
"error" : "rate_limit_exceeded" ,
"message" : "Too many requests. Please try again later." ,
"retry_after" : 60 ,
"code" : "RATE_LIMIT"
}
500 Internal Server Error
{
"error" : "internal_error" ,
"message" : "An unexpected error occurred" ,
"trace_id" : "abc123..." ,
"code" : "INTERNAL_ERROR"
}
SDK Examples
Python
import httpx
class PlaygroundClient :
def __init__ ( self , base_url : str , token : str ):
self .client = httpx.AsyncClient(
base_url = base_url,
headers = { "Authorization" : f "Bearer { token } " }
)
async def create_session ( self , name : str = None ) -> dict :
response = await self .client.post(
"/api/playground/sessions" ,
json = { "name" : name}
)
return response.json()
async def chat ( self , session_id : str , message : str ) -> dict :
response = await self .client.post(
"/api/playground/chat" ,
json = { "session_id" : session_id, "message" : message}
)
return response.json()
async def delete_session ( self , session_id : str ) -> None :
await self .client.delete( f "/api/playground/sessions/ { session_id } " )
# Usage
client = PlaygroundClient( "http://localhost:9002" , token)
session = await client.create_session( "My Session" )
response = await client.chat(session[ "session_id" ], "Hello!" )
print (response[ "content" ])
JavaScript/TypeScript
class PlaygroundClient {
private baseUrl : string ;
private token : string ;
constructor ( baseUrl : string , token : string ) {
this . baseUrl = baseUrl ;
this . token = token ;
}
async createSession ( name ?: string ) : Promise < Session > {
const response = await fetch ( ` ${ this . baseUrl } /api/playground/sessions` , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ this . token } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ name })
});
return response . json ();
}
async * streamChat ( sessionId : string , message : string ) : AsyncGenerator < ChatEvent > {
const response = await fetch ( ` ${ this . baseUrl } /api/playground/chat` , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ this . token } ` ,
'Content-Type' : 'application/json' ,
'Accept' : 'text/event-stream'
},
body: JSON . stringify ({ session_id: sessionId , message , stream: true })
});
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 );
for ( const line of chunk . split ( ' \n ' )) {
if ( line . startsWith ( 'data: ' )) {
yield JSON . parse ( line . slice ( 6 ));
}
}
}
}
}
// Usage
const client = new PlaygroundClient ( 'http://localhost:9002' , token );
const session = await client . createSession ( 'My Session' );
for await ( const event of client . streamChat ( session . session_id , 'Hello!' )) {
if ( event . type === 'token' ) {
process . stdout . write ( event . content );
}
}
Playground Guide Learn how to use the playground
Authentication API Authentication endpoints
MCP Protocol MCP message format
Observability Set up monitoring
Full API access! Use these endpoints to build custom integrations with the Interactive Playground.