Skip to content

Chat API

API per la chat AI e gestione conversazioni.

Conversazioni

Lista Conversazioni

bash
GET /api/conversations
Authorization: Bearer <token>

# Query parameters
?page=1
&limit=20
&topicId=<uuid>  # Filtra per topic

Response:

json
{
  "success": true,
  "data": [
    {
      "id": "conv-uuid",
      "title": "Domande sul contratto ACME",
      "topicId": "topic-uuid",
      "messageCount": 5,
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T11:45:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 45
  }
}

Crea Conversazione

bash
POST /api/conversations
Authorization: Bearer <token>
Content-Type: application/json

{
  "title": "Nuova conversazione",
  "topicId": "topic-uuid"  // opzionale
}

Response:

json
{
  "success": true,
  "data": {
    "id": "new-conv-uuid",
    "title": "Nuova conversazione",
    "topicId": "topic-uuid",
    "messages": []
  }
}

Dettaglio Conversazione

bash
GET /api/conversations/:conversationId
Authorization: Bearer <token>

Response:

json
{
  "success": true,
  "data": {
    "id": "conv-uuid",
    "title": "Domande sul contratto ACME",
    "topicId": "topic-uuid",
    "messages": [
      {
        "id": "msg-1",
        "role": "user",
        "content": "Qual è la durata del contratto?",
        "createdAt": "2024-01-15T10:30:00Z"
      },
      {
        "id": "msg-2",
        "role": "assistant",
        "content": "Il contratto ha durata di 24 mesi...",
        "sources": [
          {
            "documentId": "doc-uuid",
            "documentName": "Contratto_ACME.pdf",
            "page": 3,
            "score": 0.92,
            "excerpt": "...durata contrattuale di ventiquattro (24) mesi..."
          }
        ],
        "createdAt": "2024-01-15T10:30:05Z"
      }
    ]
  }
}

Elimina Conversazione

bash
DELETE /api/conversations/:conversationId
Authorization: Bearer <token>

Messaggi Chat

Invia Messaggio (Non-Streaming)

bash
POST /api/chat/message
Authorization: Bearer <token>
Content-Type: application/json

{
  "conversationId": "conv-uuid",
  "message": "Qual è la policy sulle ferie?",
  "topicId": "topic-uuid"  // opzionale, filtra retrieval
}

Response:

json
{
  "success": true,
  "data": {
    "messageId": "msg-uuid",
    "content": "Secondo la policy aziendale, ogni dipendente ha diritto a...",
    "sources": [
      {
        "documentId": "doc-uuid",
        "documentName": "Policy_HR.pdf",
        "page": 12,
        "score": 0.89,
        "excerpt": "Ogni dipendente full-time ha diritto a 25 giorni..."
      }
    ],
    "metadata": {
      "retrievalTime": 145,
      "generationTime": 2340,
      "chunksRetrieved": 8
    }
  }
}

Invia Messaggio (Streaming)

bash
POST /api/chat/stream
Authorization: Bearer <token>
Content-Type: application/json

{
  "conversationId": "conv-uuid",
  "message": "Riassumi il contratto",
  "topicId": "topic-uuid"
}

Response (SSE Stream):

event: token
data: {"content": "Il"}

event: token
data: {"content": " contratto"}

event: token
data: {"content": " prevede"}

...

event: sources
data: {"sources": [...]}

event: done
data: {"messageId": "msg-uuid"}

Gestione SSE in JavaScript

javascript
const response = await fetch('/api/chat/stream', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversationId: 'conv-uuid',
    message: 'Domanda...'
  })
})

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

while (true) {
  const { done, value } = await reader.read()
  if (done) break

  const text = decoder.decode(value)
  const lines = text.split('\n')

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6))
      console.log(data)
    }
  }
}

Documenti Temporanei

Upload Documento Temporaneo

bash
POST /api/chat/upload-temp
Authorization: Bearer <token>
Content-Type: multipart/form-data

conversationId: conv-uuid
file: <file>

Response:

json
{
  "success": true,
  "data": {
    "tempDocId": "temp-doc-uuid",
    "filename": "report.pdf",
    "status": "PROCESSING"
  }
}

Verifica Stato Elaborazione

bash
GET /api/chat/temp-doc/:tempDocId/status
Authorization: Bearer <token>

Response:

json
{
  "success": true,
  "data": {
    "status": "VECTORIZED",  // PROCESSING | VECTORIZED | ERROR
    "chunks": 45
  }
}

API Pubbliche (Widget)

Per widget embeddabili. Richiedono API Key.

Chat Non-Streaming

bash
POST /api/public/chat
X-API-Key: qk_live_xxx
Content-Type: application/json

{
  "message": "Domanda...",
  "sessionId": "session-123",  // Per mantenere contesto
  "topicId": "topic-uuid"      // Opzionale
}

Chat Streaming

bash
POST /api/public/chat/stream
X-API-Key: qk_live_xxx
Content-Type: application/json

{
  "message": "Domanda...",
  "sessionId": "session-123"
}

Lista Topics (Widget)

bash
GET /api/public/topics
X-API-Key: qk_live_xxx

Feedback

Invia Feedback

bash
POST /api/chat/feedback
Authorization: Bearer <token>
Content-Type: application/json

{
  "messageId": "msg-uuid",
  "rating": "positive",  // positive | negative
  "comment": "Risposta molto utile"  // Opzionale
}

Errori Comuni

400 Bad Request

json
{
  "error": {
    "code": "INVALID_CONVERSATION",
    "message": "Conversation not found or access denied"
  }
}

429 Rate Limited

json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Please wait.",
    "retryAfter": 60
  }
}

503 AI Service Unavailable

json
{
  "error": {
    "code": "AI_UNAVAILABLE",
    "message": "AI service temporarily unavailable"
  }
}

Best Practices

Performance

  • Usa streaming per UX migliore
  • Implementa debouncing sugli input
  • Cache le conversazioni lato client

UX

  • Mostra indicatore di caricamento durante retrieval
  • Visualizza fonti per trasparenza
  • Permetti feedback per miglioramento continuo

Error Handling

  • Gestisci timeout (max 60s per risposta)
  • Implementa retry con backoff esponenziale
  • Mostra messaggi utente-friendly per errori

Queria - Two-Tier Retrieval System