Endpoints
Riferimento completo delle API REST pubbliche di Askme AI.
Convenzioni generali
Base URL
Tutti gli endpoint sono prefissati da:
https://ai.askme.it/api/v2
Autenticazione
Ogni richiesta richiede due header:
| Header | Valore | Descrizione |
|---|---|---|
X-Api-Key | amai_<chiave> | Chiave API associata al tenant. Si genera dalla console di Askme AI. |
X-Source-App | uno tra askmechat, askmedesk, api_direct, askmeai, internal | Identifica l'applicazione che effettua la chiamata. Utile per la reportistica e l'attribuzione costi. |
Header opzionali ma raccomandati:
| Header | Tipo | Descrizione |
|---|---|---|
X-External-Id | string (max 255) | ID opaco del tuo sistema (es. ID ticket, ID ordine). Permette di correlare conversazioni e job al tuo backend. |
Idempotency-Key | string | Chiave di idempotenza per le operazioni POST critiche (creazione job di analisi). |
Paginazione
Le liste accettano i parametri standard offset e limit (default offset=0, limit=50). La risposta è sempre nel formato:
{
"items": [ ... ],
"total": 123,
"offset": 0,
"limit": 50
}
Errori
| Codice | Significato |
|---|---|
400 Bad Request | Payload non valido (es. campo obbligatorio mancante, valore fuori intervallo). |
401 Unauthorized | X-Api-Key mancante o non valida. |
403 Forbidden | La risorsa non appartiene al tenant della chiave API. |
404 Not Found | Risorsa inesistente. |
409 Conflict | Conflitto di stato (es. associazione MCP già esistente). |
413 Payload Too Large | File caricato oltre il limite consentito dal piano. |
422 Unprocessable Entity | Validazione Pydantic fallita su uno o più campi del body. |
429 Too Many Requests | Quota o rate-limit del piano superati. |
Il corpo dell'errore segue il formato FastAPI:
{ "detail": "Agent not found" }
1. Agenti
Gestione degli agenti AI: configurazione, knowledge base associate, server MCP, prompt, modelli e politiche RAG.
POST /agents
Crea un nuovo agente nel tenant.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
name | body | string (1–255) | Sì | — | Nome visualizzato dell'agente. |
description | body | string | No | — | Descrizione libera. |
model_provider | body | string | No | openai | Provider del modello. Valori: openai, anthropic, google, mistral, ollama, local. |
model_name | body | string (max 100) | No | gpt-4o-mini | Nome del modello da usare (es. gpt-4o, claude-sonnet-4-5-20250929). |
system_prompt | body | string | No | — | Prompt di sistema dell'agente. Supporta variabili {{nome_var}}. |
temperature | body | float (0.0–2.0) | No | 0.7 | Temperatura di campionamento. |
max_tokens | body | int (1–128000) | No | 2048 | Token massimi nella risposta. |
reasoning_effort | body | string | No | — | Solo per modelli con reasoning. Valori: minimal, low, medium, high. |
tools_config | body | object | No | — | Configurazione tool (function calling, structured output). |
rag_config | body | object | No | — | Configurazione RAG: retrieval_top_k, similarity_threshold, query_rewrite_mode (none/simple/multi), scope_check_enabled, disable_out_of_scope_refusal, hybrid_search, hybrid_alpha. |
handoff_config | body | object | No | — | Configurazione del passaggio a operatore umano (regole di confidenza, intent). |
output_schema | body | object (JSON Schema) | No | — | Schema JSON forzato sulla risposta del modello (structured output). |
mcp_server_ids | body | int[] | No | null | ID dei server MCP da associare. null o omesso = nessuna associazione; [] = svuota. |
parent_id | body | int | No | — | Agente genitore: il prompt di sistema effettivo è la concatenazione lungo la catena (max 10 livelli). |
is_temporary | body | bool | No | false | Se true, l'agente è nascosto dalle liste standard. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/agents" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"name": "Assistente customer care",
"description": "Risponde alle domande dei clienti su spedizioni e resi.",
"model_provider": "openai",
"model_name": "gpt-4o-mini",
"system_prompt": "Sei un assistente cortese di supporto clienti.",
"temperature": 0.4,
"max_tokens": 1024,
"mcp_server_ids": [12]
}'
Esempio risposta (201 Created)
{
"id": 87,
"tenant_id": "acme",
"name": "Assistente customer care",
"description": "Risponde alle domande dei clienti su spedizioni e resi.",
"model_provider": "openai",
"model_name": "gpt-4o-mini",
"system_prompt": "Sei un assistente cortese di supporto clienti.",
"temperature": 0.4,
"max_tokens": 1024,
"tools_config": null,
"rag_config": null,
"handoff_config": null,
"reasoning_effort": null,
"mcp_server_ids": [12],
"parent_id": null,
"is_temporary": false,
"output_schema": null,
"status": "draft",
"version": 1,
"created_by": "user-uuid",
"created_at": "2026-04-30T09:12:33Z",
"updated_at": "2026-04-30T09:12:33Z"
}
Errori specifici
| Codice | Significato |
|---|---|
400 | Nome vuoto, valore di model_provider non ammesso, oppure mcp_server_ids contiene ID non appartenenti al tenant. |
429 | Quota agents esaurita per il piano corrente. |
GET /agents
Elenca gli agenti del tenant in modo paginato.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
offset | query | int (≥0) | No | 0 | Offset di paginazione. |
limit | query | int (1–100) | No | 50 | Numero massimo di elementi. |
search | query | string | No | — | Ricerca testuale su nome e descrizione. |
status | query | string | No | — | Filtro stato. Valori: draft, active, paused, archived. |
model_name | query | string | No | — | Filtro per modello esatto. |
include_temporary | query | bool | No | false | Include agenti temporanei (creati da analisi PDF chat-with-doc). |
sort_by | query | string | No | — | Campo di ordinamento (name, created_at, updated_at). |
order | query | string | No | desc | Direzione: asc o desc. |
Esempio richiesta
curl -G "https://ai.askme.it/api/v2/agents" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
--data-urlencode "limit=20" \
--data-urlencode "status=active"
Esempio risposta (200 OK)
{
"items": [
{
"id": 87,
"tenant_id": "acme",
"name": "Assistente customer care",
"model_provider": "openai",
"model_name": "gpt-4o-mini",
"status": "active",
"version": 3,
"mcp_server_ids": [12],
"created_at": "2026-04-30T09:12:33Z",
"updated_at": "2026-04-30T11:02:00Z"
}
],
"total": 1,
"offset": 0,
"limit": 20
}
GET /agents/{agent_id}
Recupera un agente specifico.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
agent_id | path | int | Sì | Identificativo dell'agente. |
Esempio richiesta
curl "https://ai.askme.it/api/v2/agents/87" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct"
Esempio risposta (200 OK): stesso schema di POST /agents.
Errori specifici
| Codice | Significato |
|---|---|
404 | Agente non trovato o appartenente ad altro tenant. |
PUT /agents/{agent_id}
Aggiorna l'agente. Tutti i campi del body sono opzionali; solo i campi forniti vengono modificati. La modifica incrementa version e crea uno snapshot.
Attributi richiesta
Stessi campi di POST /agents, tutti opzionali. In più:
| Campo | In | Tipo | Descrizione |
|---|---|---|---|
status | body | string | Stato dell'agente. Valori: draft, active, paused, archived. |
mcp_server_ids | body | int[] | null | null = mantiene attuali; [] = rimuove tutte; [n,m] = sostituisce esattamente con questi (semantica idempotente: il backend calcola il diff e applica add/remove). |
Esempio richiesta
curl -X PUT "https://ai.askme.it/api/v2/agents/87" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"status": "active",
"temperature": 0.2,
"mcp_server_ids": [12, 15]
}'
DELETE /agents/{agent_id}
Elimina l'agente. La quota agents viene rilasciata. Risposta 204 No Content.
POST /agents/{agent_id}/rollback/{version_number}
Riporta la configurazione dell'agente a una versione precedente. Crea automaticamente una nuova entry di versione con changelog "Rollback to version N".
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
agent_id | path | int | Sì | Agente target. |
version_number | path | int | Sì | Numero di versione da ripristinare. |
Errori specifici
| Codice | Significato |
|---|---|
404 | Versione inesistente per l'agente. |
GET /agents/{agent_id}/versions
Elenca le versioni archiviate della configurazione dell'agente.
Associazioni MCP per agente
Oltre al campo mcp_server_ids nei POST/PUT /agents, sono disponibili endpoint dedicati per gestire singole associazioni:
POST /agents/{agent_id}/mcp-servers— body{ "mcp_server_id": 12 }. Risponde201o409se già associato.GET /agents/{agent_id}/mcp-servers— elenco completo dei server associati con il dettaglio.DELETE /agents/{agent_id}/mcp-servers/{mcp_server_id}— rimuove l'associazione (204o404).
2. Chat
Endpoint principale per inviare un messaggio a un agente o a un modello LLM diretto. Supporta streaming Server-Sent Events.
POST /chat
Invia un messaggio. Due modalità:
- Modalità agente: passa
agent_id. Modello, system prompt, RAG e MCP vengono dedotti dalla configurazione dell'agente. - Modalità diretta: ometti
agent_ide forniscimodel+system_promptespliciti.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
message | body | string (1–32000) | Sì | — | Testo del messaggio utente. |
agent_id | body | int | null | No* | null | ID dell'agente. *Se omesso, sono richiesti model e system_prompt. |
conversation_id | body | int | No | — | Conversazione esistente; se assente ne viene creata una nuova. |
external_conversation_id | body | string | No | — | ID conversazione del tuo sistema (alternativa a conversation_id). |
stream | body | bool | No | false | Se true la risposta è uno stream SSE. |
model | body | string | No* | — | Solo modalità diretta (es. gpt-4o-mini). |
system_prompt | body | string | No* | — | Solo modalità diretta. |
temperature | body | float | No | (default agente) | Override della temperatura. |
max_tokens | body | int | No | (default agente) | Override del limite token. |
files | body | array | No | — | Allegati: [{ filename, content_type, data }] con data base64. |
include_sources | body | bool | No | true | Se true la risposta include rag_sources. |
include_hidden_sources | body | bool | No | false | Se true include anche fonti con is_visible=false (usate ma normalmente non citate). |
template_vars | body | object (string→string) | No | — | Variabili sostituite nel system prompt (es. {{nome_cliente}}). |
classification_intents | body | array | No | — | Intent custom per la classificazione: [{ name, description }]. |
force_handoff | body | bool | No | false | Forza il passaggio a operatore umano. |
skip_handoff | body | bool | No | false | Disabilita la valutazione handoff per questo messaggio. |
skip_scope_check | body | bool | No | false | Disabilita il controllo "fuori scope" per questo messaggio. |
response_format | body | string | No | markdown | markdown o html. |
llm_response_format | body | object | No | — | Schema JSON per structured output one-shot. |
metadata | body | object | No | — | Metadati liberi propagati nel record di costo. |
mcp_auth | body | object (string→string) | No | — | Token utente per MCP che richiedono auth (passati come header per quel MCP). |
tool_approval | body | object | No | — | Risposta a un'approvazione di tool: { approved: bool, pending_message_id: int }. |
external_id | body | string (max 255) | No | — | Override dell'header X-External-Id a livello di richiesta. |
source_app | body | string (max 50) | No | — | Override dell'header X-Source-App a livello di richiesta. |
X-External-Id | header | string | No | — | ID esterno per il record di costo e attribuzione. |
Esempio richiesta (non-streaming)
curl -X POST "https://ai.askme.it/api/v2/chat" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "X-External-Id: ordine-7728" \
-H "Content-Type: application/json" \
-d '{
"agent_id": 87,
"message": "Quali sono i tempi medi di consegna in Italia?",
"stream": false
}'
Esempio risposta (200 OK, non-streaming)
{
"message_id": 5512,
"conversation_id": 4421,
"external_conversation_id": null,
"content": "I tempi medi di consegna in Italia sono compresi tra 24 e 72 ore lavorative ...",
"thinking_content": null,
"content_format": "markdown",
"role": "assistant",
"model_used": "gpt-4o-mini",
"tokens_input": 412,
"tokens_output": 88,
"latency_ms": 1430,
"rag_sources": [
{
"document_id": "117",
"chunk_id": "chunk-117-3",
"title": "Politica spedizioni",
"content_preview": "Le spedizioni standard partono entro 24 ore lavorative ...",
"relevance_score": 0.83,
"metadata": { "page": 2 },
"is_visible": true
}
],
"confidence_score": 0.91,
"needs_review": false,
"handoff_requested": false,
"handoff_reason": null,
"intent": "delivery_info",
"sentiment": "neutral",
"is_in_scope": true,
"tool_calls_count": 0,
"tools_used": [],
"pending_tool_approval": false,
"created_at": "2026-04-30T11:22:14Z"
}
Risposta in streaming (SSE)
Quando stream: true, il server risponde con Content-Type: text/event-stream. Ogni evento ha la forma:
data: {"type": "...", ...}\n\n
Tipi di evento emessi (campo type):
| Tipo | Descrizione | Campi principali |
|---|---|---|
rag_thinking | Status testuale durante la fase RAG (es. "ricerca documenti…"). | content |
thinking | Token del ragionamento interno (per modelli con reasoning). | content |
delta / content | Token incrementale della risposta. | content |
sources | Lista delle fonti RAG individuate. | sources[] |
tool_call | Il modello sta invocando un tool MCP. | tool_name, tool_args |
tool_approval_required | Tool che richiede approvazione esplicita. | pending_tool_calls[], pending_message_id |
confidence | Confidence score consolidato. | confidence_score, confidence_signals, needs_review |
handoff_decision | Decisione di handoff verso operatore umano. | handoff_requested, handoff_reason, handoff_trigger |
usage | Bilancio finale token + metadati turn. | usage.{message_id,conversation_id,model_used,tokens_input,tokens_output,latency_ms,…} |
done | Marker di fine stream. | — |
error | Errore in corso di stream. | error, code |
Esempio di stream (estratto):
data: {"type":"rag_thinking","content":"Cerco nelle fonti..."}
data: {"type":"sources","sources":[{"document_id":"117","relevance_score":0.83,...}]}
data: {"type":"delta","content":"I tempi"}
data: {"type":"delta","content":" medi di consegna"}
data: {"type":"confidence","confidence_score":0.91,"needs_review":false}
data: {"type":"usage","usage":{"message_id":5512,"conversation_id":4421,"model_used":"gpt-4o-mini","tokens_input":412,"tokens_output":88,"latency_ms":1430}}
data: {"type":"done"}
Errori specifici
| Codice | Significato |
|---|---|
400 | agent_id mancante senza model/system_prompt; message vuoto o oltre 32000 caratteri. |
404 | Agente o conversazione non trovati. |
429 | Quota messaggi del piano esaurita. |
3. Conversazioni
Storico, lookup tramite ID esterno, feedback sui messaggi.
GET /conversations
Elenca le conversazioni dell'utente corrente.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
offset | query | int | 0 | Paginazione. |
limit | query | int (1–100) | 50 | Page size. |
Esempio risposta (200 OK)
{
"items": [
{
"id": 4421,
"tenant_id": "acme",
"agent_id": 87,
"agent_name": "Assistente customer care",
"user_id": "user-uuid",
"title": "Domanda spedizioni",
"status": "active",
"message_count": 6,
"external_id": "ordine-7728",
"created_at": "2026-04-30T11:20:00Z",
"updated_at": "2026-04-30T11:24:10Z"
}
],
"total": 1,
"offset": 0,
"limit": 50
}
GET /conversations/monitoring
Vista monitoring: tutte le conversazioni del tenant (richiede permessi adeguati). Supporta filtri estesi.
Attributi richiesta
| Campo | In | Tipo | Descrizione |
|---|---|---|---|
offset, limit | query | int | Paginazione standard. |
status | query | string | Filtra per stato (active, closed, archived). |
agent_id | query | int | Filtra per agente. |
date_from | query | datetime ISO 8601 | Dalla data inclusa. |
date_to | query | datetime ISO 8601 | Fino alla data inclusa. |
GET /conversations/{conversation_id}
Dettaglio di una conversazione (senza messaggi).
Esempio risposta (200 OK)
{
"id": 4421,
"tenant_id": "acme",
"agent_id": 87,
"user_id": "user-uuid",
"title": "Domanda spedizioni",
"status": "active",
"metadata": null,
"external_id": "ordine-7728",
"insights": null,
"created_at": "2026-04-30T11:20:00Z",
"updated_at": "2026-04-30T11:24:10Z"
}
GET /conversations/by-external-id/{external_id}
Recupera la conversazione tramite l'ID esterno fornito al primo POST /chat. Utile per riprendere una sessione lato tuo backend senza tenere traccia di conversation_id interni.
Attributi richiesta
| Campo | In | Tipo | Descrizione |
|---|---|---|---|
external_id | path | string | ID opaco fornito alla creazione. |
agent_id | query | int | (opzionale) limita la ricerca a un singolo agente, utile se lo stesso external_id è stato usato con più agenti. |
Errori specifici
| Codice | Significato |
|---|---|
404 | Nessuna conversazione corrisponde all'external_id per il tenant. |
GET /conversations/{conversation_id}/messages
Recupera i messaggi della conversazione.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
conversation_id | path | int | — | Conversazione target. |
offset | query | int | 0 | Paginazione. |
limit | query | int (1–500) | 100 | Page size. |
Esempio risposta (200 OK)
{
"items": [
{
"id": 5511,
"conversation_id": 4421,
"role": "user",
"content": "Quali sono i tempi medi di consegna in Italia?",
"created_at": "2026-04-30T11:22:00Z"
},
{
"id": 5512,
"conversation_id": 4421,
"role": "assistant",
"content": "I tempi medi di consegna ...",
"tokens_input": 412,
"tokens_output": 88,
"model_used": "gpt-4o-mini",
"created_at": "2026-04-30T11:22:14Z"
}
],
"total": 2,
"offset": 0,
"limit": 100
}
PUT /conversations/{conversation_id}
Aggiorna titolo o stato della conversazione (anche PATCH).
Attributi richiesta
| Campo | In | Tipo | Descrizione |
|---|---|---|---|
title | body | string (max 500) | Nuovo titolo. |
status | body | string | active, closed o archived. |
DELETE /conversations/{conversation_id}
Elimina la conversazione e tutti i messaggi. Risposta 204 No Content.
POST /conversations/{conversation_id}/messages/{message_id}/feedback
Registra il feedback dell'utente finale su una risposta dell'assistente.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
rating | body | string | Sì | positive o negative. |
comment | body | string | No | Commento testuale. |
Esempio risposta (200 OK)
{ "message_id": 5512, "rating": "positive", "comment": "Risposta chiara." }
4. Knowledge Base
Knowledge base, documenti, FAQ, scraping web e sorgenti DB.
POST /knowledge-bases
Crea una nuova knowledge base.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
name | body | string (1–255) | Sì | — | Nome KB. |
description | body | string | No | — | Descrizione libera. |
type | body | string | No | manual | manual, scraping, db, mixed. |
embedding_model | body | string | No | text-embedding-3-small | Modello di embedding. Per modelli Mistral è obbligatorio configurare vector_store_config su Qdrant a 1024 dimensioni. |
chunk_strategy | body | string | No | recursive | Strategia di chunking. |
chunk_size | body | int (100–4000) | No | 512 | Dimensione chunk in caratteri. |
chunk_overlap | body | int (0–1000) | No | 50 | Sovrapposizione tra chunk. |
languages | body | string[] | No | ["it"] | Codici lingua ISO 639-1. Le query in lingue fuori da questo set sono auto-tradotte alla prima lingua dell'array. |
parent_id | body | int | No | — | KB genitore (per gerarchie). |
is_temporary | body | bool | No | false | KB nascosta dalle liste standard. |
vector_store_config | body | object | No | pgvector | { "provider": "pgvector", "dimensions": 1536 } oppure { "provider": "qdrant", "url": "...", "collection_name": "...", "dimensions": 1536 }. |
config | body | object | No | — | Configurazione RAG di default per la KB (override possibile a livello agente). Vedi i campi rag_config documentati nell'endpoint agenti. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/knowledge-bases" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"name": "Manuali tecnici",
"description": "Documentazione prodotto",
"type": "manual",
"languages": ["it", "en"],
"chunk_size": 800,
"chunk_overlap": 100
}'
Esempio risposta (201 Created)
{
"id": 24,
"tenant_id": "acme",
"name": "Manuali tecnici",
"description": "Documentazione prodotto",
"type": "manual",
"embedding_model": "text-embedding-3-small",
"chunk_strategy": "recursive",
"chunk_size": 800,
"chunk_overlap": 100,
"config": {},
"vector_store_config": null,
"status": "active",
"document_count": 0,
"total_chunks": 0,
"languages": ["it", "en"],
"is_temporary": false,
"parent_id": null,
"created_by": "user-uuid",
"created_at": "2026-04-30T09:00:00Z",
"updated_at": "2026-04-30T09:00:00Z"
}
GET /knowledge-bases
Elenca le knowledge base del tenant.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
offset | query | int | 0 | Paginazione. |
limit | query | int (1–100) | 50 | Page size. |
search | query | string | — | Ricerca su nome/descrizione. |
status | query | string | — | Filtro stato. |
sort_by | query | string | — | Campo di ordinamento. |
order | query | string | — | asc o desc. |
include_temporary | query | bool | false | Include KB temporanee (es. quelle create da analisi PDF chat-with-doc). |
GET /knowledge-bases/{kb_id}
Dettaglio della KB.
PATCH /knowledge-bases/{kb_id}
Aggiorna la KB (campi opzionali: name, description, status, chunk_strategy, chunk_size, chunk_overlap, config, parent_id, languages). Il vector_store_config non è modificabile dopo la creazione.
DELETE /knowledge-bases/{kb_id}
Elimina la KB, i documenti e i chunk associati. Rilascia la quota knowledge_bases. Risposta 204 No Content.
GET /knowledge-bases/{kb_id}/quality-metrics
Metriche strutturali della KB (numero documenti, distribuzione chunk, pagine scrapate, ecc.). Nessuna chiamata LLM.
Esempio risposta (200 OK)
{
"total_documents": 38,
"indexed_documents": 36,
"pending_documents": 1,
"error_documents": 1,
"doc_status_breakdown": { "indexed": 36, "pending": 1, "error": 1 },
"source_type_breakdown": { "file": 20, "url": 15, "text": 3 },
"total_chunks": 1240,
"avg_chunk_tokens": 380.4,
"min_chunk_tokens": 120,
"max_chunk_tokens": 510,
"docs_with_empty_chunks": 0,
"scraping_jobs_count": 2
}
GET /knowledge-bases/{kb_id}/export
Esporta la KB come archivio ZIP (streaming application/zip).
Documenti — /knowledge-bases/{kb_id}/documents
POST /knowledge-bases/{kb_id}/documents/upload
Carica un file (multipart). Tipi supportati: PDF, DOCX, TXT, MD, HTML, CSV, XLSX, JSON.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
file | form-data | file | Sì | — | Il file da caricare. |
priority | form-data | int | No | 2 | Priorità di elaborazione. |
category | form-data | string | No | — | Etichetta libera. |
language | form-data | string | No | — | Codice lingua. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/knowledge-bases/24/documents/upload" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-F "[email protected]" \
-F "priority=1" \
-F "language=it"
Esempio risposta (201 Created)
{
"id": 711,
"knowledge_base_id": 24,
"title": "manuale.pdf",
"source_type": "file",
"source_url": null,
"file_path": "tenant/acme/kb/24/manuale.pdf",
"mime_type": "application/pdf",
"status": "processing",
"file_size": 2148572,
"chunk_count": 0,
"metadata": null,
"error_message": null,
"created_at": "2026-04-30T09:30:00Z",
"updated_at": "2026-04-30T09:30:00Z",
"priority": 1,
"is_visible": true
}
Errori specifici
| Codice | Significato |
|---|---|
413 | File oltre il limite del piano (file_upload_size_mb). |
POST /knowledge-bases/{kb_id}/documents/text
Crea un documento da testo grezzo.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
title | body | string (1–500) | Sì | Titolo del documento. |
content | body | string (≥1) | Sì | Contenuto testuale. |
metadata | body | object | No | Metadati liberi. |
GET /knowledge-bases/{kb_id}/documents
Elenca i documenti della KB. Parametri standard di paginazione offset/limit.
GET /knowledge-bases/{kb_id}/documents/{document_id}/preview
Anteprima testuale del documento.
GET /knowledge-bases/{kb_id}/documents/{document_id}/download
Download del file originale.
DELETE /knowledge-bases/{kb_id}/documents/{document_id}
Elimina il documento e i suoi chunk. Risposta 204.
DELETE /knowledge-bases/{kb_id}/documents/bulk
Eliminazione multipla. Body: { "ids": [711, 712, 713] }.
PATCH /knowledge-bases/{kb_id}/documents/{document_id}/visibility
Mostra/nasconde il documento come fonte citata. Quando is_visible=false, il contenuto è ancora usato per il contesto RAG ma il documento non appare nelle citazioni della risposta.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
is_visible | body | bool | Sì | true per rendere visibile, false per nascondere. |
FAQ — /knowledge-bases/{kb_id}/faqs
POST /knowledge-bases/{kb_id}/faqs
Crea una FAQ.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
question | body | string (max 500) | Sì | — | Domanda canonica. |
answer | body | string (max 5000) | Sì | — | Risposta. |
category | body | string (max 255) | No | — | Categoria. |
priority | body | int | No | 2 | Priorità nel ranking. |
variants | body | string[] | No | [] | Riformulazioni alternative della domanda. |
editorial_status | body | string | No | draft | Stato editoriale (draft, published, ecc.). |
Esempio risposta (201 Created)
{
"id": 401,
"knowledge_base_id": 24,
"question": "Quali sono i tempi di consegna?",
"answer": "Le consegne avvengono entro 24-72 ore lavorative.",
"category": "spedizioni",
"priority": 1,
"variants": ["Quando arriva il pacco?", "Tempi di spedizione?"],
"editorial_status": "published",
"is_visible": true,
"created_at": "2026-04-30T10:00:00Z",
"updated_at": "2026-04-30T10:00:00Z"
}
GET /knowledge-bases/{kb_id}/faqs
Lista paginata delle FAQ.
PUT /knowledge-bases/{kb_id}/faqs/{faq_id}
Aggiornamento completo. Stessi campi di POST (tutti opzionali tranne question e answer).
DELETE /knowledge-bases/{kb_id}/faqs/{faq_id}
Eliminazione (204).
PATCH /knowledge-bases/{kb_id}/faqs/{faq_id}/visibility
Body: { "is_visible": true }. Stessa semantica di documents/{id}/visibility.
POST /knowledge-bases/{kb_id}/faqs/import
Import massivo da file CSV o JSON (multipart [email protected]). Restituisce { "imported": <int> }.
Scraping web — /knowledge-bases/{kb_id}/scraping-jobs
Riconosce automaticamente sitemap XML e feed RSS/Atom (estensioni .rss, .atom, /feed, content-type application/rss+xml, application/atom+xml).
POST /knowledge-bases/{kb_id}/scraping-jobs
Crea un job di scraping.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
url | body | string | Sì | — | URL di partenza. Può essere una pagina, una sitemap o un feed RSS/Atom. |
depth | body | int (1–5) | No | 1 | Profondità del crawl. |
schedule_cron | body | string | No | — | Cron expression per esecuzione ricorrente. |
config | body | object | No | — | Opzioni avanzate (selettori CSS, esclusioni, ecc.). |
Esempio risposta (201 Created)
{
"id": 33,
"knowledge_base_id": 24,
"url": "https://example.com/sitemap.xml",
"status": "pending",
"depth": 1,
"pages_scraped": 0,
"pages_discovered": 0,
"last_run_at": null,
"schedule_cron": null,
"trigger": "manual",
"config": null,
"error_message": null,
"created_at": "2026-04-30T10:30:00Z",
"updated_at": "2026-04-30T10:30:00Z"
}
GET /knowledge-bases/{kb_id}/scraping-jobs
Elenco dei job.
POST /knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discover
Avvia la fase di discovery (sitemap + crawl) senza scaricare le pagine. Restituisce contatori sitemap_urls_count, crawl_urls_count.
GET /knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages
Pagine trovate, paginabili. Ogni pagina ha selected: bool e status (pending, scraped, skipped, error).
PATCH /knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages/selection
Seleziona/deseleziona pagine prima dello scraping vero e proprio.
Attributi richiesta
| Campo | In | Tipo | Descrizione |
|---|---|---|---|
page_ids | body | int[] | ID specifici da modificare. |
selected | body | bool | Nuovo stato. |
select_all | body | bool | Se true ignora page_ids e applica a tutte. |
filter_source | body | string | sitemap o crawl per filtrare. |
POST /knowledge-bases/{kb_id}/scraping-jobs/{job_id}/trigger
Esegue lo scraping delle pagine selezionate. Risposta 202 Accepted.
GET /knowledge-bases/{kb_id}/scraping-jobs/{job_id}/progress
Stato di avanzamento in tempo reale del job.
DELETE /knowledge-bases/{kb_id}/scraping-jobs/{job_id}
Elimina il job (204). Per eliminazione massiva: DELETE .../scraping-jobs/bulk con body { "ids": [...] }.
Sorgenti database — /knowledge-bases/{kb_id}/db-source
PUT /knowledge-bases/{kb_id}/db-source
Crea o aggiorna la configurazione di una sorgente DB (un solo connettore per KB).
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
connection_type | body | string | Sì | postgresql, mysql, mssql. |
name | body | string | No | Nome del connettore. |
host | body | string | Sì | Host del DB. |
port | body | int (1–65535) | Sì | Porta. |
database | body | string | Sì | Nome del database. |
username | body | string | Sì | Utente. |
password | body | string | No | Password. Cifrata at-rest. |
schema | body | string | No | Nome dello schema (PostgreSQL/MSSQL). |
table | body | string | No | Tabella sorgente (alternativa a query). |
query | body | string | No | Query SQL custom (alternativa a table). |
sync_interval_minutes | body | int (≥1) | No | Intervallo di sync in minuti. Convertito internamente in cron. |
POST /knowledge-bases/{kb_id}/db-source/test
Verifica la connessione senza salvarla. Stessi campi di PUT esclusi gli attributi di sync. Risponde { "success": true|false, "message": "..." }.
GET /knowledge-bases/{kb_id}/db-source/preview
Anteprima di poche righe dalla sorgente configurata. Risposta:
{
"rows": [
{ "id": 1, "title": "...", "content": "..." }
],
"columns": ["id", "title", "content"]
}
POST /knowledge-bases/{kb_id}/db-source/run
Avvia un'estrazione manuale. Risposta:
{
"documents_created": 124,
"rows_processed": 124,
"message": "Estrazione completata."
}
GET /knowledge-bases/{kb_id}/db-source/{connector_id}/runs
Storico esecuzioni (started_at, completed_at, rows_extracted, chunks_created, error_message).
DELETE /knowledge-bases/{kb_id}/db-source/{connector_id}/runs
Pulisce lo storico esecuzioni del connettore (204).
DELETE /knowledge-bases/{kb_id}/db-source/{connector_id}
Elimina la sorgente DB (204).
Ricerca — /search
POST /search
Ricerca ibrida (vettoriale + BM25 + RRF + FAQ) su una o più KB.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
query | body | string (1–2000) | Sì | — | Testo della query. |
knowledge_base_ids | body | int[] | Sì | — | Almeno una KB. |
top_k | body | int (1–100) | No | 10 | Numero di risultati. |
min_score | body | float (0.0–1.0) | No | 0.0 | Soglia minima di rilevanza. |
use_reranking | body | bool | No | false | Abilita il reranker (cross-encoder o Cohere). |
enable_bm25 | body | bool | No | true | Includi BM25 nella fusione RRF. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/search" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"query": "tempi medi consegna Italia",
"knowledge_base_ids": [24],
"top_k": 5,
"use_reranking": true
}'
Esempio risposta (200 OK)
{
"query": "tempi medi consegna Italia",
"chunks": [
{
"id": "chunk-117-3",
"document_id": 117,
"knowledge_base_id": 24,
"content": "Le spedizioni standard partono entro 24 ore lavorative ...",
"score": 0.83,
"metadata": { "page": 2 }
}
],
"faqs": [
{
"id": 401,
"knowledge_base_id": 24,
"question": "Quali sono i tempi di consegna?",
"answer": "Le consegne avvengono entro 24-72 ore lavorative.",
"score": 0.92,
"is_visible": true
}
],
"total_results": 6,
"search_time_ms": 132.4
}
Endpoint atomici
Stesso DTO di /search. Differiscono per la strategia retrieval, utili in pipeline di fan-out:
POST /search/advanced— ricerca con filtri estesi e reranking. Accetta?document_ids=...(lista) come query string.POST /search/vector— solo retrieval vettoriale puro (no BM25, no rerank, no fusion).POST /search/fulltext— solo BM25 / Postgres FTS (KB con vector store esterno solamente vengono ignorate).POST /search/faq— solo FAQ matching (vettoriale + opzionale BM25 con RRF). I risultati sono nel campofaqs;chunksè sempre vuoto.
5. Server MCP
Server MCP (Model Context Protocol) registrati a livello tenant e associabili agli agenti.
POST /mcp-servers
Registra un nuovo server MCP.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
name | body | string (1–255) | Sì | Nome visualizzato. |
description | body | string | No | Descrizione libera. |
transport | body | string | Sì | Trasporto. Valori: stdio, sse, streamable-http. |
command | body | string (max 500) | Solo per stdio | Comando eseguibile. |
args | body | string[] | No | Argomenti del comando. |
url | body | string (max 500) | Solo per sse/streamable-http | URL del server. |
env | body | object (string→string) | No | Variabili ambiente (per stdio) o header custom. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/mcp-servers" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"name": "Calendar MCP",
"description": "Server MCP per gestione calendario",
"transport": "streamable-http",
"url": "https://mcp.example.com/calendar",
"env": { "Authorization": "Bearer ..." }
}'
Esempio risposta (201 Created)
{
"id": 12,
"tenant_id": "acme",
"name": "Calendar MCP",
"description": "Server MCP per gestione calendario",
"transport": "streamable-http",
"command": null,
"args": null,
"url": "https://mcp.example.com/calendar",
"env": { "Authorization": "Bearer ..." },
"status": "unknown",
"tools_count": 0,
"tools_cache": null,
"last_health_check": null,
"created_at": "2026-04-30T10:50:00Z",
"updated_at": "2026-04-30T10:50:00Z"
}
Errori specifici
| Codice | Significato |
|---|---|
400 | Validazione fallita (es. transport=sse senza url, transport=stdio senza command). |
GET /mcp-servers
Elenca i server MCP del tenant. Filtri: search, status, transport, oltre a offset/limit.
GET /mcp-servers/{server_id}
Dettaglio + cache dei tool.
PATCH /mcp-servers/{server_id}
Aggiorna il server (campi opzionali). Stessi vincoli di trasporto.
DELETE /mcp-servers/{server_id}
Elimina il server (204).
GET /mcp-servers/{server_id}/tools
Restituisce i tool esposti dal server, con relativo input_schema (JSON Schema).
POST /mcp-servers/{server_id}/refresh-tools
Forza il refresh della cache tool dal server. Restituisce conteggio e lista aggiornata.
POST /mcp-servers/{server_id}/test
Esegue un test di connessione live. Risposta { "success": bool, "message": string }.
Health
Lo stato status del server è cacheato in DB. Le chiamate di health probano i server in tempo reale e persistono il risultato.
GET /mcp-servers/health
Stato cacheato di tutti i server (nessuna probe). Restituisce un array di McpServerResponse.
POST /mcp-servers/health/refresh
Probe live in parallelo di tutti i server e persiste i risultati.
POST /mcp-servers/{server_id}/health/refresh
Probe live di un singolo server.
6. Analisi
Job di analisi orchestrati: contenuto testuale, PDF, CV, dati strutturati, classificazione, OCR.
Modello di esecuzione: ogni POST /analysis/<tipo> accetta il body, restituisce 202 Accepted con un job in stato pending e schedula l'elaborazione asincrona. Si interroga poi GET /analysis/{id} per ottenere il risultato. Per i tipi che lo supportano sono disponibili anche le varianti /sync che attendono il completamento (200 OK).
Header opzionale Idempotency-Key: se ripetuto entro la finestra di idempotenza, restituisce lo stesso job invece di crearne uno nuovo.
Opzioni comuni (options)
Tutti i body POST espongono un campo opzionale options:
| Campo | Tipo | Default | Descrizione |
|---|---|---|---|
model | string | — | Override del modello LLM (es. claude-haiku-4-5-20251001). |
temperature | float (0.0–2.0) | — | Sampling temperature. |
max_tokens | int (1–128000) | — | Limite token risposta. |
language | string | — | Hint lingua (it, en, ecc.). |
output_format | string | json | json, html, markdown. |
guardrails | bool | false | Abilita controlli PII/injection/toxicity. |
confidence_check | bool | false | Abilita validazione qualità risultato. |
webhook_id | int | — | Webhook (registrato con /webhooks) da notificare a fine job. |
Inoltre tutti i body accettano:
| Campo | Tipo | Descrizione |
|---|---|---|
template_id | int | ID di un template di analisi: il suo input_config viene fuso col body. |
name | string (max 255) | Nome visualizzato del job. |
POST /analysis/content
Analisi testuale generica (sentiment, entità, parole chiave, riassunto).
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
text | body | string (1–200000) | Sì | — | Testo da analizzare. |
custom_instructions | body | string (max 4000) | No | — | Istruzioni aggiuntive per il prompt. |
max_chars | body | int (100–200000) | No | 20000 | Troncamento prima dell'invio al modello. |
template_id, name, options | body | — | No | — | (vedi sopra). |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/analysis/content" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Idempotency-Key: 2c9e5c0e-..." \
-H "Content-Type: application/json" \
-d '{
"name": "Analisi recensione",
"text": "Il prodotto è arrivato con un giorno di ritardo ma il servizio clienti è stato ottimo.",
"options": { "language": "it" }
}'
Esempio risposta (202 Accepted)
{
"id": 88102,
"tenant_id": "acme",
"type": "content",
"status": "pending",
"input_config": {
"name": "Analisi recensione",
"text": "Il prodotto è arrivato con un giorno di ritardo...",
"max_chars": 20000,
"source_app": "api_direct"
},
"result": null,
"error_message": null,
"created_by": "user-uuid",
"started_at": null,
"completed_at": null,
"created_at": "2026-04-30T11:00:00Z"
}
L'endpoint POST /analysis/content/sync ha lo stesso body ma attende il completamento e risponde 200 OK col result popolato.
POST /analysis/pdf
Analisi di un documento PDF tramite LLM. Opzionalmente crea una KB temporanea + agente per la modalità chat-with-doc.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
filename | body | string (max 512) | Sì | — | Nome del file (determina nome KB/agente). |
file_content | body | string base64 | Sì* | — | Contenuto PDF in base64. *Esattamente uno tra file_content e file_path. |
file_path | body | string | Sì* | — | Path su object storage di un file già caricato. |
custom_prompt | body | string (max 8000) | No | — | Istruzioni libere per l'analisi. |
agent_id | body | int | No | — | Agente di fallback per il prompt. |
temp_agent_name | body | string (max 512) | No | — | Nome dell'agente temporaneo (richiesto in alcune lingue). |
create_kb_agent | body | bool | No | false | Se true, crea KB+agente temporanei con il documento per la chat. |
skip_analysis | body | bool | No | false | Salta lo step di analisi LLM e crea solo KB+agente. Richiede create_kb_agent=true. |
template_id, name, options | body | — | No | — | (vedi sopra). |
Esempio risposta (202 Accepted)
{
"id": 88103,
"tenant_id": "acme",
"type": "pdf",
"status": "pending",
"input_config": {
"filename": "policy.pdf",
"create_kb_agent": true,
"skip_analysis": false,
"source_app": "api_direct"
},
"result": null,
"created_at": "2026-04-30T11:05:00Z"
}
Errori specifici
| Codice | Significato |
|---|---|
422 | Né file_content né file_path forniti, oppure entrambi; oppure skip_analysis=true senza create_kb_agent=true. |
L'endpoint /pdf/sync esegue sincrono.
POST /analysis/cv
Scoring di un CV contro le job position configurate dal tenant.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
file_content | body | string base64 | Sì | CV (PDF o DOCX) in base64. |
filename | body | string (max 512) | Sì | Nome file con estensione (determina parser). |
job_position_id | body | int | No | Limita lo scoring a una posizione. Se omesso, valuta contro tutte le posizioni del tenant. |
cv_prompt_id | body | int | No | Override del prompt CV. Default: prompt configurato dal tenant. |
template_id, name, options | body | — | No | (vedi sopra). |
L'endpoint /cv/sync esegue sincrono.
POST /analysis/data
Analisi su dati tabellari (CSV/XLSX letti come lista di dict).
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
data | body | object[] (1–10000) | Sì | Righe come { colonna: valore }. |
columns | body | string[] | No | Sottoinsieme di colonne da analizzare (default: tutte). |
custom_prompt | body | string (max 4000) | No | Istruzioni LLM aggiuntive. |
agent_id | body | int | No | Agente di fallback per il prompt. |
template_id, name, options | body | — | No | (vedi sopra). |
7. Classificazione (catalogo Similarity)
La classificazione di testi avviene attraverso il catalogo Similarity: si costruisce un indice a partire da esempi (con o senza etichette) e poi si classificano nuovi testi rispetto a quell'indice. Tutti gli endpoint sono prefissati da /api/v2/analysis/catalogs.
POST /analysis/catalogs/build
Avvia la build di un catalogo. Risposta 202 Accepted: la build è asincrona, polling sullo stato del catalogo.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
name | body | string (1–100) | Sì | — | Nome del catalogo. |
mode | body | string | Sì | — | supervised (richiede label_path su almeno una coppia) o unsupervised. |
threshold | body | float (0.0–1.0) | No | 0.6 | Soglia minima di similarità per accettare un candidato. |
pairs | body | object[] | Sì | — | Lista non vuota di coppie. Ogni elemento: ticket (string, obbligatorio), response (string), label_path (string[]). |
Esempio richiesta (supervisionato)
curl -X POST "https://ai.askme.it/api/v2/analysis/catalogs/build" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"name": "Triage richieste clienti",
"mode": "supervised",
"threshold": 0.6,
"pairs": [
{ "ticket": "Vorrei sapere quando arriva il pacco", "label_path": ["spedizione"] },
{ "ticket": "Il prodotto è arrivato rotto", "label_path": ["reso"] },
{ "ticket": "Posso modificare l'\''indirizzo di consegna?", "label_path": ["modifica ordine"] }
]
}'
Esempio risposta (202 Accepted)
{
"id": 14,
"tenant_id": "c9fe50b1-be08-...",
"name": "Triage richieste clienti",
"mode": "supervised",
"status": "queued",
"refinement_status": "templates_refined",
"embedding_model": "text-embedding-3-small",
"threshold": 0.6,
"template_count": 0,
"created_by": "...",
"created_at": "2026-04-30T12:00:00Z"
}
Errori specifici
| Codice | Significato |
|---|---|
400 | pairs vuoto; oppure mode=supervised senza alcuna coppia con label_path. |
GET /analysis/catalogs
Lista paginata dei cataloghi del tenant.
Query
| Campo | Tipo | Default | Descrizione |
|---|---|---|---|
offset | int | 0 | Indice del primo elemento. |
limit | int (1–200) | 50 | Numero di elementi. |
status | string | — | Filtro per stato: queued, building, ready, failed, cancelled. |
mode | string | — | supervised o unsupervised. |
GET /analysis/catalogs/{catalog_id}
Dettaglio del catalogo, inclusa la lista dei templates (esempi rappresentativi). Da usare per esplorare i cluster nei cataloghi non supervisionati o le etichette in quelli supervisionati.
DELETE /analysis/catalogs/{catalog_id}
Elimina il catalogo. Può essere invocata anche su un catalogo in stato building: la cancellazione interrompe la build.
POST /analysis/catalogs/classify
Classifica uno o più testi rispetto a un catalogo ready e restituisce i candidati top-N con punteggio di similarità.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
catalog_id | body | int | Sì | — | ID del catalogo. |
texts | body | string[] | Sì | — | Testi da classificare. |
top_n | body | int (1–10) | No | 3 | Numero di candidati per testo. |
threshold_override | body | float (0.0–1.0) | No | — | Sovrascrive la soglia del catalogo per questa chiamata. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/analysis/catalogs/classify" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-H "Content-Type: application/json" \
-d '{
"catalog_id": 14,
"texts": ["Quando arriva il mio ordine?", "L'\''articolo che ho ricevuto è difettoso"],
"top_n": 3
}'
Esempio risposta
{
"catalog_id": 14,
"catalog_name": "Triage richieste clienti",
"catalog_mode": "supervised",
"refinement_status": "templates_refined",
"total_texts": 2,
"processing_time_seconds": 0.42,
"threshold_used": 0.6,
"top_n": 3,
"results": [
{
"text": "Quando arriva il mio ordine?",
"candidates": [
{ "label_path": ["spedizione"], "similarity": 0.91, "template_id": 22, "template_text": "Vorrei sapere quando arriva il pacco" }
],
"best_label_path": ["spedizione"],
"best_similarity": 0.91,
"verdict": "strong"
}
],
"distribution": { "spedizione": 1, "reso": 1 }
}
verdict è uno di strong, medium, weak, none ed è calcolato sul punteggio del primo candidato e sul delta col secondo.
GET /analysis/catalogs/queue-status
Stato della coda di build (depth, in-flight, dead-letter).
POST /analysis/catalogs/{catalog_id}/requeue
Rilancia un catalogo in stato failed o cancelled.
POST /analysis/catalogs/{catalog_id}/refine-labels
Affina i nomi dei cluster (solo cataloghi non supervisionati) con un passaggio LLM.
POST /analysis/catalogs/{catalog_id}/refine-templates
Seleziona i template più rappresentativi per ciascun cluster.
PATCH /analysis/catalogs/{catalog_id}/templates/{template_id}
Modifica manualmente testo o label_path di un singolo template.
Body
| Campo | Tipo | Descrizione |
|---|---|---|
text | string | Nuovo testo del template. |
label_path | string[] | Nuova etichetta. |
DELETE /analysis/catalogs/{catalog_id}/templates/{template_id}
Rimuove un template dal catalogo.
POST /analysis/ocr
Estrazione di testo da immagini o PDF scansionati. Multipart/form-data (non JSON).
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
file | form-data | file | Sì | — | Immagine o PDF (max 50 MB). |
language | form-data | string | No | ita | Lingua Tesseract: ita, eng, fra, deu, spa. |
template_id | form-data | int | No | — | Template OCR. |
webhook_id | form-data | int | No | — | Webhook di notifica a completamento. |
Esempio richiesta
curl -X POST "https://ai.askme.it/api/v2/analysis/ocr" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-F "[email protected]" \
-F "language=ita"
Errori specifici
| Codice | Significato |
|---|---|
400 | Tipo MIME non supportato o file vuoto. |
413 | File oltre 50 MB. |
GET /analysis
Elenca i job di analisi del tenant.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
offset | query | int | 0 | Paginazione. |
limit | query | int (1–200) | 50 | Page size. |
status | query | string | — | pending, running, completed, failed. |
type | query | string | — | content, pdf, cv, data, ocr. |
Esempio risposta (200 OK)
{
"items": [
{
"id": 88102,
"tenant_id": "acme",
"type": "content",
"status": "completed",
"input_config": { "name": "Analisi recensione", "source_app": "api_direct" },
"error_message": null,
"created_by": "user-uuid",
"started_at": "2026-04-30T11:00:01Z",
"completed_at": "2026-04-30T11:00:08Z",
"created_at": "2026-04-30T11:00:00Z"
}
],
"total": 1,
"offset": 0,
"limit": 50
}
GET /analysis/{analysis_id}
Dettaglio del job, incluso result (struttura specifica per tipo).
Esempio risposta (200 OK, content analysis completata)
{
"id": 88102,
"tenant_id": "acme",
"type": "content",
"status": "completed",
"input_config": { "text": "...", "source_app": "api_direct" },
"result": {
"summary": "Il cliente segnala un ritardo ma riconosce la qualità del servizio.",
"sentiment": { "label": "neutral", "score": 0.62 },
"keywords": ["ritardo", "servizio clienti"],
"entities": [{ "text": "servizio clienti", "type": "department" }],
"language": "it"
},
"error_message": null,
"started_at": "2026-04-30T11:00:01Z",
"completed_at": "2026-04-30T11:00:08Z",
"created_at": "2026-04-30T11:00:00Z"
}
GET /analysis/{analysis_id}/status
Solo lo stato del job (no result). Adatto al polling frequente.
Esempio risposta (200 OK)
{
"id": 88102,
"type": "content",
"status": "running",
"started_at": "2026-04-30T11:00:01Z",
"completed_at": null,
"error_message": null
}
DELETE /analysis/{analysis_id}
Soft-delete del job. Risposta 204.
7. Monitoring
Utilizzo, costi e dashboard. I valori monetari (cost_usd) sono visibili solo a profili specifici; per gli altri sono restituiti azzerati (i conteggi token e record restano accurati).
GET /usage
Elenca i record di utilizzo del tenant.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
start_time | query | datetime ISO 8601 | — | Inizio finestra. |
end_time | query | datetime ISO 8601 | — | Fine finestra. |
service | query | string | — | Filtra per servizio (es. ai-core, knowledge). |
offset, limit | query | int | 0, 100 | Paginazione (limit max 1000). |
Esempio risposta (200 OK)
{
"items": [
{
"id": 9001,
"tenant_id": "acme",
"service": "ai-core",
"resource": "chat",
"operation": "message",
"quantity": 1,
"unit": "message",
"metadata": { "agent_id": 87 },
"timestamp": "2026-04-30T11:22:14Z"
}
],
"total": 1,
"offset": 0,
"limit": 100
}
GET /costs/summary
Sintesi costi del periodo, con breakdown per servizio, modello, operazione, source app, cost tier e giorno.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
start_time | query | datetime ISO 8601 | Sì | Inizio finestra. |
end_time | query | datetime ISO 8601 | Sì | Fine finestra. |
service | query | string | No | Filtro. |
model | query | string | No | Filtro. |
source_app | query | string | No | Filtro. |
operation_type | query | string | No | Filtro su metadata.operation_type. |
cost_tier | query | string | No | Filtro. |
Esempio richiesta
curl -G "https://ai.askme.it/api/v2/costs/summary" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
--data-urlencode "start_time=2026-04-01T00:00:00Z" \
--data-urlencode "end_time=2026-04-30T23:59:59Z"
Esempio risposta (200 OK)
{
"tenant_id": "acme",
"start_time": "2026-04-01T00:00:00Z",
"end_time": "2026-04-30T23:59:59Z",
"total_cost_usd": "12.4810",
"total_input_tokens": 412300,
"total_output_tokens": 88142,
"by_service": [
{ "key": "ai-core", "total_cost_usd": "10.20", "total_input_tokens": 320000, "total_output_tokens": 64000, "record_count": 1102 }
],
"by_model": [
{ "key": "gpt-4o-mini", "total_cost_usd": "8.10", "total_input_tokens": 290000, "total_output_tokens": 60000, "record_count": 980 }
],
"by_operation_type": [
{ "key": "chat.generation", "total_cost_usd": "9.40", "total_input_tokens": 300000, "total_output_tokens": 70000, "record_count": 950 }
],
"by_source_app": [
{ "key": "api_direct", "total_cost_usd": "5.20", "total_input_tokens": 150000, "total_output_tokens": 30000, "record_count": 410 }
],
"by_date": [
{ "date": "2026-04-01", "total_cost_usd": "0.42", "total_input_tokens": 11200, "total_output_tokens": 2820 }
]
}
GET /costs/by-category
Breakdown costi per operation_type (es. chat.generation, chat.query_rewrite, chat.rerank, analysis.pdf, ecc.).
Attributi richiesta: start_time, end_time (entrambi obbligatori).
Esempio risposta (200 OK)
[
{ "key": "chat.generation", "total_cost_usd": 9.40, "total_input_tokens": 300000, "total_output_tokens": 70000, "record_count": 950 },
{ "key": "chat.query_rewrite", "total_cost_usd": 0.20, "total_input_tokens": 8000, "total_output_tokens": 1200, "record_count": 410 },
{ "key": "unknown", "total_cost_usd": 0.00, "total_input_tokens": 1200, "total_output_tokens": 200, "record_count": 12 }
]
I record privi del tag finiscono nel bucket unknown.
Endpoint analoghi: GET /costs/by-service, GET /costs/by-model, GET /costs/by-source-app, GET /costs/by-cost-tier.
GET /costs
Lista paginata dei singoli record di costo con filtri estesi (service, model, source_app, operation_type, cost_tier, conversation_id, turn_id, external_id, agent_id, is_streaming).
GET /costs/conversations/{conversation_id}/turns
Riepilogo costi per ogni turn della conversazione.
GET /costs/turns/{turn_id}/events
Tutti gli eventi di costo di un singolo turn (utile per audit dettagliato).
GET /dashboard/metrics
Metriche aggregate per la dashboard (cache ~2s).
Esempio risposta (200 OK)
{
"conversationsToday": 142,
"conversationsChange": 8.2,
"activeAgents": 12,
"activeAgentsChange": 0.0,
"knowledgeBases": 6,
"mtdCost": 4.81,
"mtdCostChange": -3.4,
"handoffsToday": 4,
"handoffsChange": 33.3,
"quotaUsagePercent": 42.0,
"quotaUsageChange": 5.1,
"isSuperAdmin": false
}
GET /dashboard/trend
Trend conversazioni per giorno (parametro days, default 30).
GET /dashboard/top-agents
Classifica degli agenti per volume di conversazioni.
GET /metrics
Metriche Prometheus in formato testo (text/plain). Endpoint operativo, generalmente consumato dal sistema di monitoring infrastrutturale.
8. Prompt Templates
Template di prompt riutilizzabili e versionabili.
POST /prompt-templates
Crea un template.
Attributi richiesta
| Campo | In | Tipo | Obbligatorio | Default | Descrizione |
|---|---|---|---|---|---|
name | body | string (1–255) | Sì | — | Nome del template. |
content | body | string | Sì | — | Testo del prompt; può contenere {{variabile}}. |
role | body | string | No | system | Ruolo del messaggio (system, user, assistant). |
description | body | string | No | — | Descrizione. |
variables | body | array | No | [] | [{ name, description, default_value }]. |
parent_id | body | int | No | — | Template genitore. |
tags | body | string[] | No | [] | Tag liberi. |
status | body | string | No | draft | draft, published, archived. |
Esempio risposta (201 Created)
{
"id": 55,
"tenant_id": "acme",
"name": "Saluto cliente",
"description": "Apertura standard delle conversazioni di supporto",
"content": "Buongiorno {{nome_cliente}}, sono l'assistente di {{azienda}}.",
"role": "system",
"variables": [
{ "name": "nome_cliente", "description": "Nome del cliente", "default_value": "" },
{ "name": "azienda", "description": "Nome azienda", "default_value": "Askme" }
],
"parent_id": null,
"tags": ["welcome", "support"],
"status": "draft",
"version": 1,
"created_by": "user-uuid",
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-04-30T12:00:00Z"
}
GET /prompt-templates
Elenca i template.
Attributi richiesta
| Campo | In | Tipo | Default | Descrizione |
|---|---|---|---|---|
parent_id | query | int | — | Filtra per template genitore. |
status | query | string | — | Filtro stato. |
search | query | string | — | Ricerca testuale. |
root_only | query | bool | false | Se true mostra solo i template senza genitore. |
offset, limit | query | int | 0, 50 | Paginazione (limit max 200). |
PUT /prompt-templates/{template_id}
Aggiornamento (campi opzionali). Incrementa version.
DELETE /prompt-templates/{template_id}
Eliminazione (204).
Operazioni non esposte
Le operazioni amministrative non documentate qui (es. provisioning di tenant, gestione piani e quote, configurazione globale del sistema) non sono accessibili tramite la chiave API tenant. Per queste necessità contatta il team IT di Askme.