API: Chat ========== Base URL: ``/projects/{projectId}/chat`` The chat API provides AI-assisted co-design coaching with streaming support and form trigger generation. Endpoints ---------- Create Thread ~~~~~~~~~~~~~~ .. code-block:: http POST /projects/{projectId}/chat **Request Body:** .. code-block:: json { "project_context": { "projectId": "uuid", "projectName": "Climate Resilience Service" }, "phase": 1 } **Response (201):** .. code-block:: json { "thread_id": "uuid", "projectId": "project-uuid", "phase": 1, "intro_message": "Welcome to Phase 1! Let's start by identifying...", "createdAt": "2026-01-15T10:30:00Z" } List Threads ~~~~~~~~~~~~~ .. code-block:: http GET /projects/{projectId}/chat Returns all threads for the authenticated user in this project. **Response (200):** .. code-block:: json [ { "thread_id": "uuid", "phase": 1, "lastMessage": "Help me identify stakeholders", "messageCount": 12, "createdAt": "2026-01-15T10:30:00Z" } ] Get Thread ~~~~~~~~~~~ .. code-block:: http GET /projects/{projectId}/chat/{thread_id} Send Message ~~~~~~~~~~~~~ .. code-block:: http POST /projects/{projectId}/chat/{thread_id}/messages **Request Body:** .. code-block:: json { "content": "Help me create a stakeholder card for the local municipality", "stream": false } **Response (200) — Non-streaming:** .. code-block:: json { "message_id": "uuid", "role": "assistant", "content": "I'll help you create a stakeholder card for the local municipality...", "status": "completed", "follow_up_options": [ "Add assessment scores", "Create another stakeholder", "Generate ecosystem matrix" ], "form_trigger": { "templateCode": "1.0.1", "action": "create", "fields": { "formalInfo_name": "Local Municipality", "formalInfo_type": "Public administration", "formalInfo_location": "City, Country" } }, "token_usage": { "prompt_tokens": 1200, "completion_tokens": 350 } } **Streaming Response:** When ``stream=true``, the response uses Server-Sent Events (SSE): .. code-block:: text data: {"type": "token", "content": "I'll"} data: {"type": "token", "content": " help"} data: {"type": "token", "content": " you"} ... data: {"type": "follow_up", "options": ["Add assessment", "Create another"]} data: {"type": "form_trigger", "data": {...}} data: {"type": "done"} Get Thread Messages ~~~~~~~~~~~~~~~~~~~~ .. code-block:: http GET /projects/{projectId}/chat/{thread_id}/messages **Response (200):** .. code-block:: json [ { "message_id": "uuid", "role": "user", "content": "Help me identify stakeholders", "timestamp": "2026-01-15T10:30:00Z" }, { "message_id": "uuid", "role": "assistant", "content": "Based on your project...", "follow_up_options": [...], "timestamp": "2026-01-15T10:30:05Z" } ] Delete Thread ~~~~~~~~~~~~~~ .. code-block:: http DELETE /projects/{projectId}/chat/{thread_id} **Response (204):** No content. Frontend Integration --------------------- **Streaming example (JavaScript):** .. code-block:: javascript async function sendMessage(projectId, threadId, content) { const response = await fetch( `/projects/${projectId}/chat/${threadId}/messages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ content, 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); const lines = chunk.split('\n').filter(l => l.startsWith('data: ')); for (const line of lines) { const data = JSON.parse(line.slice(6)); switch (data.type) { case 'token': appendToMessage(data.content); break; case 'follow_up': showFollowUpButtons(data.options); break; case 'form_trigger': openTemplateForm(data.data); break; } } } }