Esempi di integrazione
Flussi end-to-end pronti da adattare. Tutti gli esempi assumono di aver generato una API key dalla console (vedi Manuale → Chiavi API).
Setup
# Variabili d'ambiente — non committarle in chiaro
export ASKMEAI_HOST="https://ai.askme.it"
export ASKMEAI_API_KEY="amai_xxxxxxxxxxxxxxxx"
export ASKMEAI_SOURCE_APP="api_direct"
Header obbligatori in ogni richiesta:
X-Api-Key: $ASKMEAI_API_KEYX-Source-App: $ASKMEAI_SOURCE_APP(lista chiusa:askmechat,askmedesk,api_direct,askmeai,internal)Content-Type: application/jsonsui POST/PUT/PATCH
Header opzionale ma consigliato:
X-External-Id: <id-correlation>per propagare un identificativo del tuo sistema nei record di costo.
1. Chat con un agente
cURL
curl -X POST "$ASKMEAI_HOST/api/v2/chat" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP" \
-H "X-External-Id: ticket-9281" \
-H "Content-Type: application/json" \
-d '{
"agent_id": 12,
"message": "Quali sono i tempi medi di consegna?",
"stream": false
}'
Python (httpx)
import os
import httpx
client = httpx.Client(
base_url=os.environ["ASKMEAI_HOST"] + "/api/v2",
headers={
"X-Api-Key": os.environ["ASKMEAI_API_KEY"],
"X-Source-App": os.environ.get("ASKMEAI_SOURCE_APP", "api_direct"),
},
timeout=30.0,
)
resp = client.post("/chat", json={
"agent_id": 12,
"message": "Quali sono i tempi medi di consegna?",
"stream": False,
}, headers={"X-External-Id": "ticket-9281"})
resp.raise_for_status()
data = resp.json()
print(data["message"]["content"])
Node.js (fetch)
const HOST = process.env.ASKMEAI_HOST;
const API_KEY = process.env.ASKMEAI_API_KEY;
const resp = await fetch(`${HOST}/api/v2/chat`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'X-Source-App': 'api_direct',
'X-External-Id': 'ticket-9281',
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent_id: 12,
message: 'Quali sono i tempi medi di consegna?',
stream: false,
}),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
console.log(data.message.content);
2. Chat in streaming (SSE)
Cambia stream: true nel body. La risposta è text/event-stream.
Python (httpx + SSE manuale)
import json, os, httpx
with httpx.stream(
"POST",
os.environ["ASKMEAI_HOST"] + "/api/v2/chat",
headers={
"X-Api-Key": os.environ["ASKMEAI_API_KEY"],
"X-Source-App": "api_direct",
"Content-Type": "application/json",
"Accept": "text/event-stream",
},
json={"agent_id": 12, "message": "Riassumi la policy resi", "stream": True},
timeout=None,
) as resp:
resp.raise_for_status()
for raw in resp.iter_lines():
if not raw or not raw.startswith("data: "):
continue
evt = json.loads(raw[6:])
if evt.get("type") == "delta":
print(evt["content"], end="", flush=True)
elif evt.get("type") == "done":
print()
break
Eventi tipici dello stream: rag_thinking, delta, confidence, handoff_decision, usage, done.
3. Lista agenti paginata
curl -G "$ASKMEAI_HOST/api/v2/agents" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP" \
--data-urlencode "offset=0" \
--data-urlencode "limit=20"
Response:
{
"items": [
{ "id": 12, "name": "Assistente Vendite", "status": "active", "model": "gpt-4o-mini" }
],
"total": 4,
"offset": 0,
"limit": 20
}
4. Caricamento documento in una Knowledge Base
import os, httpx
with open("policy-resi.pdf", "rb") as f:
files = {"file": ("policy-resi.pdf", f, "application/pdf")}
resp = httpx.post(
f"{os.environ['ASKMEAI_HOST']}/api/v2/knowledge-bases/3/documents",
headers={
"X-Api-Key": os.environ["ASKMEAI_API_KEY"],
"X-Source-App": "api_direct",
},
files=files,
timeout=120,
)
resp.raise_for_status()
print(resp.json())
L'ingest è asincrono: lo stato passa per pending → processing → ready. Verifica con GET /knowledge-bases/3/documents/{doc_id}.
5. Analisi PDF
curl -X POST "$ASKMEAI_HOST/api/v2/analysis/pdf" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP" \
-F "[email protected]" \
-F 'options={"language":"it","create_kb_agent":true,"skip_analysis":false}'
Risposta sincrona contiene job_id. Polling dello stato:
curl -s "$ASKMEAI_HOST/api/v2/analysis/$JOB_ID/status" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP"
Quando status == "completed", il dettaglio (GET /analysis/{job_id}) include result.response con la risposta dell'LLM.
6. Classificazione con catalogo Similarity
La classificazione di testi avviene in due passi: prima si costruisce un catalogo dai propri esempi, poi si interroga il catalogo con nuovi testi.
6.1 Costruzione del catalogo (una tantum)
curl -X POST "$ASKMEAI_HOST/api/v2/analysis/catalogs/build" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP" \
-H "Content-Type: application/json" \
-d '{
"name": "Triage richieste",
"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"] },
{ "ticket": "Vorrei un preventivo per la versione enterprise", "label_path": ["vendita"] }
]
}'
Risposta 202 con id del catalogo. Polling sullo stato:
curl "$ASKMEAI_HOST/api/v2/analysis/catalogs/$CATALOG_ID" \
-H "X-Api-Key: $ASKMEAI_API_KEY" -H "X-Source-App: $ASKMEAI_SOURCE_APP"
Quando status == "ready" il catalogo è pronto.
6.2 Classifica nuovi testi
curl -X POST "$ASKMEAI_HOST/api/v2/analysis/catalogs/classify" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP" \
-H "Content-Type: application/json" \
-d "{
\"catalog_id\": $CATALOG_ID,
\"texts\": [
\"Quando arriva il mio ordine?\",
\"L'articolo è difettoso, vorrei restituirlo\"
],
\"top_n\": 3
}"
La risposta è sincrona e contiene per ciascun testo i candidati top-N con similarity e verdict (strong/medium/weak/none).
7. Lookup conversazione tramite ID esterno
Utile quando il chiamante mantiene un proprio identificativo di conversazione:
curl "$ASKMEAI_HOST/api/v2/conversations/by-external-id/ordine-7728" \
-H "X-Api-Key: $ASKMEAI_API_KEY" \
-H "X-Source-App: $ASKMEAI_SOURCE_APP"
Per agganciare i messaggi successivi alla stessa conversazione, passa conversation_id nel body del POST /chat.
Errori comuni
| Codice | Causa | Soluzione |
|---|---|---|
401 | X-Api-Key mancante o invalido | Verifica header e prefisso amai_ |
400 | X-Source-App con valore fuori lista chiusa | Usa uno tra askmechat, askmedesk, api_direct, askmeai, internal |
403 | Permesso insufficiente del ruolo della chiave | Aggiorna scope/ruolo in Amministrazione → Chiavi API |
429 | Rate limit o quota di piano superati | Implementa backoff esponenziale e leggi Retry-After |
Best practice
- Usa
X-External-Idper correlare i log del tuo sistema con i record di costo Askme AI. - Tieni il valore di
X-Source-Appcoerente per integrazione (non variare ad ogni chiamata). - In Python preferisci
httpx.Clientriusabile (sessione) all'apertura/chiusura ad ogni richiesta. - Implementa retry su
429con jitter esponenziale. - Per chat con agente verifica sempre la quota
conversations_per_monthlato monitoring se la frequenza è alta.