sequenceDiagram
autonumber
participant C as Client
participant IDP as Mock IDP<br/>/mock-idp/*
participant A as Auth Router<br/>/auth/login
participant ADS as AppDataService
participant DB as PostgreSQL<br/>(app schema)
note over C,IDP: Step 1 — Obtain IDP token (development only)
C ->> IDP: POST /mock-idp/authenticate<br/>{ idp_user_id }
IDP -->> C: { access_token: JWT(sub=idp_user_id) }
note over C,DB: Step 2 — Exchange IDP token for App Session
C ->> A: POST /auth/login<br/>{ idp_token, id_provider, user_type,<br/>language, origin, capabilities }
A ->> IDP: GET /.well-known/jwks.json
IDP -->> A: { keys: [{ alg: HS256, k: secret_key }] }
A ->> A: jwt.decode(idp_token, secret_key)<br/>→ extract sub claim (login_id)
A ->> ADS: initialize_app_session(context)
ADS ->> DB: SELECT IDPLogin<br/>WHERE (idp, login_id)
alt Returning user
DB -->> ADS: IDPLogin found
ADS ->> DB: SELECT User WHERE id = idp_login.user_id
DB -->> ADS: User record
ADS ->> DB: UPDATE User SET last_seen_at = now()
else New user
DB -->> ADS: No IDPLogin found
ADS ->> DB: INSERT User (user_type, language, age_class)
DB -->> ADS: New User record
ADS ->> DB: INSERT IDPLogin (idp, login_id, user_id)
end
ADS ->> DB: UPSERT AppSession (user_id, origin, capabilities)
DB -->> ADS: AppSession record
ADS ->> DB: COMMIT
opt Returning user
ADS ->> DB: SELECT Conversations<br/>WHERE user_id ORDER BY updated_at DESC
DB -->> ADS: UserHistory
end
ADS -->> A: AuthResponse
A -->> C: { bearer_token, app_session, user_history }
note over C: Store bearer_token → Authorization: Bearer token;
Client Development & Integration
Last updated: 2026-04-13
Client Development Guide
This guide specifies the protocol for building client applications (Web, Mobile, Bots) that interact with the StopCyberViolences API. It covers authentication, session management, capability negotiation, feature flags, and real-time communication.
1. Client Identification & Origin Tracking
All clients must identify themselves using an Origin Identifier. This field is mandatory for telemetry tracking (Langfuse) and capability profile resolution.
- Field:
origin(string) - Mandatory - Common Values:
web_react,discord,dev_terminal. - Custom Clients: Use a unique slug (e.g.,
ios_app,android_app).
2. Authentication Flow
The application uses an IDP-based authentication flow. Clients obtain a signed token from an Identity Provider (IDP) and exchange it for an application-scoped session.
Step 1 — Obtain an IDP Token
Clients authenticate with the Identity Provider (e.g., Orange IDP, Google, or the mock IDP for development) and receive a JWT token.
Development (Mock IDP):
POST /api/v1/mock-idp/authenticate
Body: { "idp_user_id": "test-user-123" }
# Returns: { "access_token": "<signed-jwt>" }The mock IDP signs the token with a symmetric key (HS256). Its public key is exposed at GET /mock-idp/.well-known/jwks.json so the auth router can verify it without out-of-band configuration.
Step 2 — Exchange Token for App Session
POST /api/v1/auth/login
Request Body:
{
"idp_token": "<jwt-from-step-1>",
"id_provider": "mock-idp",
"user_type": "teenager",
"age_class": "cycle3",
"language": "FR",
"origin": "web_react",
"capabilities": {
"supports_sse": true
}
}Response (AuthResponse):
{
"bearer_token": "uuid-of-app-session",
"app_session": { "id": "uuid-of-app-session", "origin": "web_react", ... },
"user_history": {
"user_id": "uuid",
"conversations": [
{
"id": "uuid",
"current_monster": "betty",
"summary": "...",
"updated_at": "2026-04-01T12:00:00Z"
}
]
}
}The bearer_token (currently the app_session UUID) must be stored and sent as Authorization: Bearer <token> on all subsequent requests. user_history contains the user’s previous conversations and can be used to offer session resumption.
3. Capability Negotiation
The system uses a 3-tier negotiation system to adapt its behavior to the client’s features.
Priority Levels
- Explicit Declaration: Capabilities provided by the client in the
auth/loginrequest (Highest priority). - Registry Lookup: Backend looks up the
originin theclient_registry(defined inapi/config.py). - Safe Defaults: System-wide safe defaults used if the origin is unknown.
Note: If the provided capabilities fail validation, the system automatically falls back to the origin’s registry profile or safe system defaults.
Supported Capabilities
| Flag | Type | Description |
|---|---|---|
supports_sse |
Boolean | If true, the backend enables streaming callbacks (Server-Sent Events) for this session. |
4. Feature Flags
Before rendering the UI, clients should fetch the current feature flags:
GET /api/v1/features?variant=teenager&environment=development
Response:
{
"enable_monster_flip_animation": true,
"enable_simple_resume_prompt": true,
"enable_login_screen": true,
"collective_management": false
}Flags are evaluated against variant and environment context. Frontend clients should respect these flags to enable or disable UI features.
5. Session Lifecycle
Initializing a Chat Session
Endpoint: POST /api/v1/chat/init
After authentication, clients must initialize a chat session before sending messages. This endpoint requires the Authorization: Bearer <bearer_token> header obtained from /auth/login.
Request Body:
{
"resume_conversation_id": null
}Response Metadata: The response contains a session_id (a UUID) which must be included in all subsequent requests.
Resuming a Previous Conversation
If user_history.conversations is non-empty, offer the user the option to resume. To resume, call /chat/init with the specific resume_conversation_id. If enable_simple_resume_prompt is true, the backend will automatically restore the conversation summary from the persistent store and prime the agent with the previous context.
Sending Messages
Endpoint: POST /api/v1/chat
{
"message": "Hello, I need help.",
"session_id": "uuid-from-init",
"attachments": ["path/to/previously/uploaded/file.png"]
}Interactive State Selection
When the bot is awaiting a specific selection (emotion or dropdown), use these endpoints:
Emotion Selection
Endpoint: POST /api/v1/chat/emotion
{
"emotion": "sad",
"session_id": "uuid-from-init"
}Dropdown Selection
Endpoint: POST /api/v1/chat/dropdown
{
"selection": "option_key",
"session_id": "uuid-from-init"
}Handling Dynamic State
Clients must synchronize their UI based on the ChatResponse metadata returned in every turn:
- Active Monster: The
monsterfield indicates which character is speaking. - Interactive Flags:
awaiting_emotion_selection: Iftrue, render an emotion picker usingemotion_options.awaiting_dropdown_selection: Iftrue, render a selection menu usingdropdown_options. The question to display is indropdown_question.
6. Real-time Streaming (SSE)
If supports_sse is negotiated as true, establish a persistent connection for real-time updates.
Endpoint: GET /api/v1/chat/{session_id}/events/listen
Event Protocol
- handshake: Payload:
{}(connection confirmation) - settings: Payload:
{"data": {"monster": "..."}}or{"data": {"language": "..."}}(state updates) - terminate: Payload:
{}(stream end signal)
7. Conversation History
Endpoint: GET /api/v1/chat/history
Returns a UserHistory object with all past conversations for the authenticated user. Used to populate the ConversationHistoryModal or the SimpleResumePrompt in the web client.
8. Session Settings
Endpoint: POST /api/v1/chat/settings/change
Allows changing the language or the monster for the active session.
Request Body:
{
"session_id": "uuid",
"language": "EN",
"monster": "moustache"
}9. Media & Accessibility
File Uploads
Upload media (screenshots, pasted images) to POST /api/v1/files/upload before sending the chat message. Use the returned file paths in the attachments array. Images pasted directly into the chat input are automatically uploaded by the web client.
Voice Integration
For voice-first clients, use POST /api/v1/audio/transcribe to convert speech to text.