Endpoint: Knowledge Base
Riferimento degli endpoint per la gestione delle basi di conoscenza, dei documenti, delle FAQ, delle sorgenti web e database, della ricerca e dei webhook di notifica.
Tutte le richieste usano l'URL base https://ai.askme.it/api/v2 e le intestazioni descritte in Autenticazione. Gli elenchi seguono la paginazione offset/limit descritta nella Panoramica. Gli endpoint delle basi di conoscenza richiedono che la funzionalità knowledge_bases sia attiva per l'organizzazione; accanto a ogni endpoint è indicato, dove rilevante, il permesso che gli scope della chiave devono coprire.
1. Basi di conoscenza
POST /knowledge-bases
Crea una base di conoscenza. Permesso: knowledge_bases.create.
Attributi della richiesta
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
name | body | string (1–255) | Sì | — | Nome della base di conoscenza. |
description | body | string | No | — | Descrizione libera. |
type | body | string | No | manual | Origine prevalente dei contenuti: manual (documenti e FAQ caricati), web (pagine di siti web), database (sorgente database), api (contenuti inviati da un'integrazione). |
embedding_model | body | string | No | text-embedding-3-small | Modello usato per indicizzare e cercare i contenuti. Non si può cambiare dopo la creazione. |
chunk_strategy | body | string | No | recursive | Strategia di suddivisione dei documenti in frammenti. |
chunk_size | body | int (100–4000) | No | 512 | Dimensione dei frammenti. |
chunk_overlap | body | int (0–1000) | No | 50 | Sovrapposizione tra frammenti consecutivi; deve essere minore di chunk_size. |
languages | body | string[] | No | ["it"] | Lingue dei contenuti (codici ISO 639-1). Le domande in lingue diverse vengono tradotte nella prima lingua dell'elenco prima della ricerca. |
parent_id | body | int | No | — | Base di conoscenza genitore. |
is_temporary | body | bool | No | false | Se true, la base non compare negli elenchi standard. |
config | body | object | No | — | Impostazioni di lettura dei documenti. Si consiglia di lasciarlo vuoto: il recupero delle informazioni è regolato dalla piattaforma e non legge questo campo. |
Esempio di 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": "Documentazione interna",
"description": "Listino, onboarding e procedure interne",
"type": "manual",
"languages": ["it"]
}'
Esempio di risposta (201 Created)
{
"id": 12,
"tenant_id": "5b0e2f7a-2c41-4d0e-9a6b-1c9e8f3d4a21",
"name": "Documentazione interna",
"description": "Listino, onboarding e procedure interne",
"type": "manual",
"embedding_model": "text-embedding-3-small",
"chunk_strategy": "recursive",
"chunk_size": 512,
"chunk_overlap": 50,
"config": {},
"vector_store_config": null,
"status": "active",
"document_count": 0,
"total_chunks": 0,
"website_count": 0,
"faq_count": 0,
"pending_documents": 0,
"error_documents": 0,
"storage_bytes": 0,
"created_by": "apikey:28",
"created_at": "2026-09-24T16:39:00.667513Z",
"updated_at": "2026-09-24T16:39:00.667513Z",
"parent_id": null,
"languages": ["it"],
"is_temporary": false,
"tenant_wide_editable": true
}
Errori specifici
| Codice | Significato |
|---|---|
422 | Validazione non superata, per esempio chunk_overlap non minore di chunk_size o type fuori elenco. |
429 | Quota knowledge_bases del piano esaurita. |
GET /knowledge-bases
Elenca le basi di conoscenza dell'organizzazione. Permesso: knowledge_bases.read.
| Campo | In | Tipo | Predefinito | Descrizione |
|---|---|---|---|---|
offset | query | int | 0 | Paginazione. |
limit | query | int (1–100) | 50 | Dimensione della pagina. |
search | query | string | — | Ricerca su nome e descrizione. |
status | query | string | — | active, inactive, building, error. |
sort_by, order | query | string | — | Ordinamento; order vale asc o desc. |
include_temporary | query | bool | false | Include le basi temporanee (per esempio quelle create dall'analisi PDF per conversare con un documento). |
GET /knowledge-bases/{kb_id}
Dettaglio della base di conoscenza, nello stesso formato di POST /knowledge-bases.
PATCH /knowledge-bases/{kb_id}
Aggiorna la base di conoscenza. Permesso: knowledge_bases.update. Campi facoltativi: name, description, status, chunk_strategy, chunk_size, chunk_overlap, config, parent_id, languages. vector_store_config ed embedding_model non sono modificabili dopo la creazione: una richiesta di cambio del modello viene rifiutata. Le nuove impostazioni di suddivisione valgono per i documenti elaborati dopo la modifica.
DELETE /knowledge-bases/{kb_id}
Elimina la base di conoscenza con i suoi documenti e libera la quota knowledge_bases. Permesso: knowledge_bases.delete. Risposta 204 No Content.
Se uno o più agenti usano la base, la richiesta viene rifiutata con 409 e il corpo elenca gli agenti coinvolti:
{
"detail": {
"code": "KB_HAS_LINKED_AGENTS",
"agents": [
{ "id": 54, "name": "Assistente sito", "status": "active" }
]
}
}
Per procedere si ripete la richiesta con il parametro agents:
| Valore | Effetto |
|---|---|
?agents=detach | Toglie la base di conoscenza dalla configurazione degli agenti, che restano attivi. |
?agents=pause | Porta in stato paused gli agenti attivi che la usano, senza modificarne la configurazione. |
curl -X DELETE "https://ai.askme.it/api/v2/knowledge-bases/12?agents=detach" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx"
Se non tutti gli agenti possono essere aggiornati, la base non viene eliminata e la risposta 502 (code: AGENT_RELEASE_PARTIAL_FAILURE) riporta in released_agent_ids e failed_agent_ids gli agenti aggiornati e quelli non aggiornati. La richiesta può essere ripetuta senza effetti sugli agenti già aggiornati.
GET /knowledge-bases/{kb_id}/agents
Agenti che consultano la base di conoscenza. Permesso: knowledge_bases.read. Risposta { "items": [...], "total": n }.
POST /knowledge-bases/{kb_id}/reindex
Ricalcola in background i contatori della base di conoscenza a partire dai documenti presenti. Permesso: knowledge_bases.reindex. Risponde 202 con { "id": 12, "status": "building" }; al termine lo stato torna active (oppure error). Se una reindicizzazione è già in corso la risposta è 409. L'operazione non rielabora i contenuti: per rigenerare i frammenti di un documento si usa POST .../documents/{document_id}/process, per una sorgente web si rilancia il job di scraping.
GET /knowledge-bases/{kb_id}/quality-metrics
Metriche strutturali della base di conoscenza, calcolate senza chiamate ai modelli.
{
"total_documents": 6,
"indexed_documents": 5,
"pending_documents": 0,
"error_documents": 1,
"doc_status_breakdown": { "error": 1, "indexed": 5 },
"source_type_breakdown": { "file": 6 },
"total_chunks": 5,
"avg_chunk_tokens": 157.4,
"min_chunk_tokens": 90,
"max_chunk_tokens": 236,
"docs_with_empty_chunks": 0,
"total_scraped_pages": 0,
"scraped_pages_done": 0,
"scraped_pages_pending": 0,
"scraped_pages_excluded": 0,
"avg_unique_content_ratio": 0.0,
"scraping_jobs_count": 0
}
GET /knowledge-bases/{kb_id}/export
Esporta la base di conoscenza come archivio ZIP (application/zip).
GET /knowledge-bases/{kb_id}/change-log
Cronologia delle modifiche della base di conoscenza (documenti aggiunti, sostituiti, eliminati): action, actor_id, actor_type, details, created_at. Paginazione offset/limit (predefinito 20, massimo 100).
2. Documenti
Endpoint sotto /knowledge-bases/{kb_id}/documents.
Un documento caricato o creato da testo è in stato pending finché non viene elaborato, cioè suddiviso in frammenti e indicizzato con POST .../documents/{document_id}/process. Solo i documenti in stato indexed vengono consultati dagli agenti. Gli stati possibili sono pending, processing, processed, indexed ed error.
POST /knowledge-bases/{kb_id}/documents/upload
Carica un file (multipart). Permesso: knowledge_bases.upload. Formati gestiti: PDF, DOCX, TXT, MD, HTML, CSV, XLSX, JSON.
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
file | form-data | file | Sì | — | File da caricare. |
priority | form-data | int | No | 2 | Priorità della fonte (1 = più alta). |
category | form-data | string | No | — | Categoria libera, salvata nei metadati. |
language | form-data | string | No | — | Lingua del documento. |
Esempio di richiesta (cURL)
curl -X POST "https://ai.askme.it/api/v2/knowledge-bases/12/documents/upload" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "X-Source-App: api_direct" \
-F "[email protected]" \
-F "category=Listino" \
-F "language=it"
Esempio di richiesta (Python, httpx), con elaborazione
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": "api_direct"},
timeout=120.0,
)
with open("listino-servizi.pdf", "rb") as fh:
resp = client.post(
"/knowledge-bases/12/documents/upload",
files={"file": ("listino-servizi.pdf", fh, "application/pdf")},
data={"category": "Listino", "language": "it"},
)
resp.raise_for_status()
document = resp.json()
resp = client.post(f"/knowledge-bases/12/documents/{document['id']}/process")
resp.raise_for_status()
print(resp.json()["status"], resp.json()["chunk_count"])
Esempio di risposta (201 Created)
{
"id": 137,
"knowledge_base_id": 12,
"title": "listino-servizi.pdf",
"source_type": "file",
"source_url": null,
"file_path": "5b0e2f7a-2c41-4d0e-9a6b-1c9e8f3d4a21/12/listino-servizi.pdf",
"mime_type": "application/pdf",
"status": "pending",
"file_size": 18342,
"chunk_count": 0,
"metadata": { "category": "Listino", "language": "it" },
"error_message": null,
"created_at": "2026-09-24T16:41:12.114807Z",
"updated_at": "2026-09-24T16:41:12.114807Z",
"priority": 2,
"is_visible": true
}
Errori specifici
| Codice | Significato |
|---|---|
413 | File oltre il limite di dimensione del piano. |
429 | Quota dei documenti o dello spazio di archiviazione esaurita. |
POST /knowledge-bases/{kb_id}/documents/text
Crea un documento da testo. Permesso: knowledge_bases.upload. Come per i file, il documento va poi elaborato.
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
title | body | string (1–500) | Sì | Titolo del documento. |
content | body | string | Sì | Testo del documento. |
metadata | body | object | No | Metadati liberi. |
POST /knowledge-bases/{kb_id}/documents/{document_id}/process
Elabora il documento: estrae il testo, lo suddivide in frammenti e lo indicizza. Permesso: knowledge_bases.update. Per impostazione predefinita l'elaborazione è sincrona e la risposta (200) riporta il documento con lo stato finale (indexed, oppure error con error_message). Con ?background=true la risposta è immediata (202, stato processing) e l'esito si legge con GET .../documents/{document_id}. La stessa chiamata rielabora un documento già indicizzato.
POST /knowledge-bases/{kb_id}/documents/{document_id}/replace
Sostituisce il file di un documento mantenendone l'identificativo, così che le citazioni e i collegamenti esistenti restino validi. Permesso: knowledge_bases.upload.
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
file | form-data | file | Sì | Nuovo file. |
title | form-data | string | No | Nuovo titolo. |
background | query | bool | No | Se true, la rielaborazione avviene in background (202). |
Il nuovo contenuto viene elaborato subito: la risposta riporta il documento aggiornato.
Altri endpoint dei documenti
| Endpoint | Metodo | Descrizione |
|---|---|---|
/knowledge-bases/{kb_id}/documents | GET | Elenco dei documenti, con paginazione. |
/knowledge-bases/{kb_id}/documents/{document_id} | GET | Dettaglio del documento, con stato ed eventuale error_message. |
/knowledge-bases/{kb_id}/documents/{document_id}/preview | GET | Anteprima del testo estratto. |
/knowledge-bases/{kb_id}/documents/{document_id}/download | GET | Scarica il file originale. |
/knowledge-bases/{kb_id}/documents/{document_id} | DELETE | Elimina il documento e i suoi frammenti (204). |
/knowledge-bases/{kb_id}/documents/bulk | DELETE | Eliminazione multipla, corpo { "document_ids": [137, 138] }. |
/knowledge-bases/{kb_id}/documents/{document_id}/visibility | PATCH | Corpo { "is_visible": false }: il documento resta usato per costruire le risposte, ma non compare tra le fonti mostrate agli utenti finali (fonte nascosta). |
3. FAQ
Endpoint sotto /knowledge-bases/{kb_id}/faqs. Solo le FAQ in stato editoriale verified vengono usate dagli agenti.
POST /knowledge-bases/{kb_id}/faqs
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
question | body | string (max 500) | Sì | — | Domanda. |
answer | body | string (max 5000) | Sì | — | Risposta. |
category | body | string (max 255) | No | — | Categoria. |
priority | body | int | No | 2 | Priorità della FAQ come fonte. |
variants | body | string[] | No | [] | Formulazioni alternative della domanda. |
editorial_status | body | string | No | draft | draft, verified, obsolete. |
Esempio di risposta (201 Created)
{
"id": 401,
"knowledge_base_id": 11,
"question": "Che cos'è Askme AI?",
"answer": "Askme AI è la piattaforma per creare agenti conversazionali che rispondono usando le basi di conoscenza dell'organizzazione.",
"category": "Prodotto",
"created_at": "2026-09-24T17:12:04.215771Z",
"updated_at": "2026-09-24T17:12:04.215771Z",
"priority": 2,
"variants": ["A cosa serve Askme AI?"],
"editorial_status": "verified",
"is_visible": true
}
Altri endpoint delle FAQ
| Endpoint | Metodo | Descrizione |
|---|---|---|
/knowledge-bases/{kb_id}/faqs | GET | Elenco paginato. |
/knowledge-bases/{kb_id}/faqs/{faq_id} | PUT | Aggiornamento: question e answer obbligatori, gli altri campi (compreso is_visible) facoltativi. |
/knowledge-bases/{kb_id}/faqs/{faq_id} | DELETE | Eliminazione (204). |
/knowledge-bases/{kb_id}/faqs | DELETE | Elimina tutte le FAQ della base di conoscenza. |
/knowledge-bases/{kb_id}/faqs/{faq_id}/visibility | PATCH | Corpo { "is_visible": false }, con lo stesso significato della visibilità dei documenti. |
/knowledge-bases/{kb_id}/faqs/visibility | PATCH | Stessa operazione su tutte le FAQ della base di conoscenza. |
/knowledge-bases/{kb_id}/faqs/import | POST | Importazione da file CSV o JSON (multipart [email protected]). Risposta { "imported": 12 }. |
/knowledge-bases/{kb_id}/faqs/template/{formato} | GET | File modello per l'importazione, in formato csv o json. |
4. Scraping web
Endpoint sotto /knowledge-bases/{kb_id}/scraping-jobs. Il servizio riconosce automaticamente sitemap XML e feed RSS/Atom.
POST /knowledge-bases/{kb_id}/scraping-jobs
Crea un job di scraping.
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
url | body | string | Sì | — | Indirizzo di partenza: una pagina, una sitemap o un feed. |
depth | body | int (1–5) | No | 1 | Profondità di esplorazione dei collegamenti. |
schedule_cron | body | string | No | — | Espressione cron per l'esecuzione periodica. |
exclude_urls | body | string[] | No | — | Indirizzi da escludere, confrontati come prefisso di host e percorso (per esempio www.esempio.it/area-riservata). |
exclude_paths | body | string[] | No | — | Percorsi da escludere su qualunque host (per esempio /team/, /privacy-policy). |
exclude_patterns | body | string[] | No | — | Espressioni regolari confrontate con l'indirizzo completo. |
config | body | object | No | — | Opzioni avanzate. |
Esempio di risposta (201 Created)
{
"id": 6,
"knowledge_base_id": 10,
"url": "https://www.lascaux.it",
"status": "pending",
"depth": 3,
"pages_scraped": 0,
"pages_discovered": 0,
"pages_failed": 0,
"last_run_at": null,
"schedule_cron": null,
"trigger": "manual",
"config": { "exclude_paths": ["/team", "/privacy-policy"] },
"error_message": null,
"created_at": "2026-09-24T14:44:50.289701Z",
"updated_at": "2026-09-24T14:44:50.289701Z"
}
Altri endpoint dello scraping
| Endpoint | Metodo | Descrizione |
|---|---|---|
/knowledge-bases/{kb_id}/scraping-jobs | GET | Elenco dei job. |
/knowledge-bases/{kb_id}/scraping-jobs/detect-sitemap | POST | Cerca la sitemap di un sito: corpo { "url": "https://www.esempio.it" }, risposta { "sitemap_url", "pages" }. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id} | GET, PATCH, DELETE | Dettaglio, modifica (stessi campi della creazione, facoltativi), eliminazione (204). |
/knowledge-bases/{kb_id}/scraping-jobs/bulk | DELETE | Eliminazione multipla, corpo { "ids": [6, 7] }. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discover | POST | Individua le pagine (sitemap ed esplorazione dei collegamenti) senza scaricarle. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages | GET | Pagine individuate, con selected e status (pending, scraped, skipped, error). |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages/selection | PATCH | Seleziona o deseleziona pagine: page_ids, selected, oppure select_all con il filtro facoltativo filter_source (sitemap o crawl). |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages/{page_id} | DELETE | Rimuove una pagina individuata e il contenuto importato. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages/{page_id}/visibility | PATCH | Nasconde o mostra la pagina come fonte, come per i documenti. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/discovered-pages/{page_id}/preview | GET | Testo importato per la pagina: document_id, title, url, preview_text, total_chars. Una pagina non ancora importata restituisce un'anteprima vuota. |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/trigger | POST | Avvia l'importazione delle pagine selezionate (202). |
/knowledge-bases/{kb_id}/scraping-jobs/{job_id}/progress | GET | Avanzamento del job in tempo reale (stream SSE). |
5. Sorgenti database
Endpoint sotto /knowledge-bases/{kb_id}/db-source. Una sorgente database importa periodicamente righe di una tabella o di una query come documenti. Nella versione attuale è gestito il tipo di connessione postgresql.
PUT /knowledge-bases/{kb_id}/db-source
Crea o aggiorna la sorgente database della base di conoscenza.
| Campo | In | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|---|
connection_type | body | string | Sì | postgresql. |
name | body | string | No | Nome della sorgente. |
host | body | string | Sì | Host del database. |
port | body | int (1–65535) | Sì | Porta. |
database | body | string | Sì | Nome del database. |
username | body | string | Sì | Utente, preferibilmente con sola lettura. |
password | body | string | No | Password, conservata cifrata. |
schema | body | string | No | Schema. |
table | body | string | No | Tabella da importare (in alternativa a query). |
query | body | string | No | Query SQL di lettura (in alternativa a table). |
sync_interval_minutes | body | int (≥1) | No | Intervallo di sincronizzazione in minuti. |
Altri endpoint delle sorgenti database
| Endpoint | Metodo | Descrizione |
|---|---|---|
/knowledge-bases/{kb_id}/db-source | GET | Configurazione corrente (la password non viene restituita). |
/knowledge-bases/{kb_id}/db-source/test | POST | Verifica la connessione senza salvarla (stessi campi di PUT): { "success": bool, "message": string }. |
/knowledge-bases/{kb_id}/db-source/preview | GET | Anteprima di alcune righe: { "rows": [...], "columns": [...] }. |
/knowledge-bases/{kb_id}/db-source/run | POST | Avvia un'importazione manuale: { "documents_created", "rows_processed", "message" }. |
/knowledge-bases/{kb_id}/db-source/{connector_id}/runs | GET, DELETE | Storico delle esecuzioni (started_at, completed_at, rows_extracted, chunks_created, error_message) e sua cancellazione. |
/knowledge-bases/{kb_id}/db-source/{connector_id} | DELETE | Elimina la sorgente (204). |
6. Ricerca
Endpoint per interrogare direttamente le basi di conoscenza, senza passare da un agente.
POST /search
Ricerca ibrida (vettoriale e testuale, con fusione dei risultati e FAQ) su una o più basi di conoscenza.
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
query | body | string (1–2000) | Sì | — | Testo da cercare. |
knowledge_base_ids | body | int[] | Sì | — | Almeno una base di conoscenza. |
top_k | body | int (1–100) | No | 10 | Numero di risultati. |
min_score | body | float (0.0–1.0) | No | 0.0 | Punteggio minimo. |
use_reranking | body | bool | No | false | Riordina i risultati con il modello di riordino, se disponibile nell'installazione. |
enable_bm25 | body | bool | No | true | Include la ricerca testuale nella fusione. |
Esempio di richiesta
curl -X POST "https://ai.askme.it/api/v2/search" \
-H "X-Api-Key: amai_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"query": "orari del supporto tecnico",
"knowledge_base_ids": [11, 12],
"top_k": 5
}'
Esempio di risposta (200 OK)
{
"query": "orari del supporto tecnico",
"chunks": [
{
"id": "42",
"document_id": 139,
"knowledge_base_id": 12,
"content": "Il supporto tecnico risponde dal lunedì al venerdì, dalle 9 alle 18 [...]",
"score": 0.031,
"metadata": { "category": "Procedure", "language": "it" }
}
],
"faqs": [
{
"id": 401,
"knowledge_base_id": 11,
"question": "Quali sono gli orari del supporto?",
"answer": "Il supporto è attivo dal lunedì al venerdì, dalle 9 alle 18.",
"score": 0.92,
"is_visible": true
}
],
"total_results": 6,
"search_time_ms": 132.4
}
Varianti
Le varianti accettano lo stesso corpo e restituiscono lo stesso formato:
POST /search/advanced: ricerca con filtri aggiuntivi; accetta?document_ids=...per limitare i documenti;POST /search/vector: solo ricerca vettoriale;POST /search/fulltext: solo ricerca testuale;POST /search/faq: solo FAQ; i risultati sono nel campofaqsechunksè vuoto.
7. Webhook
I webhook inviano una notifica HTTP POST a un indirizzo dell'integrazione quando si verificano eventi nell'organizzazione (documenti caricati o eliminati, scraping completati, agenti creati, analisi concluse, ...). Permessi: admin.integrations.read per la lettura, admin.integrations.manage per le modifiche.
POST /webhooks
| Campo | In | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|---|
name | body | string | Sì | — | Nome del webhook. |
url | body | string | Sì | — | Indirizzo che riceve le notifiche. |
events | body | string[] | No | [] | Tipi di evento notificati (elenco con GET /webhooks/event-types). |
secret | body | string | No | — | Segreto per la firma delle notifiche. Se ne può generare uno con POST /webhooks/generate-secret. |
active | body | bool | No | true | Webhook attivo. |
Esempio di risposta (201 Created)
{
"id": 3,
"tenant_id": "5b0e2f7a-2c41-4d0e-9a6b-1c9e8f3d4a21",
"name": "Notifiche documenti",
"url": "https://integrazione.example.com/askme/webhook",
"secret": "***",
"events": ["document.uploaded", "document.deleted"],
"active": true,
"created_at": "2026-09-24T15:02:11.402118+00:00",
"updated_at": "2026-09-24T15:02:11.402118+00:00",
"last_delivery_at": null,
"last_delivery_outcome": null
}
Il segreto non viene mai restituito: le letture riportano "***" quando un segreto è impostato. In un aggiornamento, inviando di nuovo "***" il segreto resta invariato; un valore diverso lo sostituisce.
Firma e formato delle notifiche
Ogni notifica ha questo formato:
{
"event_id": "7f1c1f0e-5c1a-4f47-9d2b-2f5e1b0c9a44",
"event_type": "document.uploaded",
"tenant_id": "5b0e2f7a-2c41-4d0e-9a6b-1c9e8f3d4a21",
"timestamp": "2026-09-24T15:10:02.118Z",
"data": { "kb_id": 12, "document_id": 137, "title": "listino-servizi.pdf" }
}
event_id è univoco per ogni invio e consente di ignorare eventuali duplicati. Se il webhook ha un segreto, la notifica contiene l'intestazione X-Askme-Signature: sha256=<firma>, dove la firma è l'HMAC-SHA256 esadecimale del corpo della richiesta calcolato con il segreto. Esempio di verifica in Python:
import hashlib
import hmac
def signature_is_valid(body: bytes, header_value: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header_value or "")
Una notifica è considerata consegnata quando l'indirizzo risponde con un codice 2xx. In caso di errore 5xx o di mancata risposta l'invio viene ripetuto fino a tre tentativi; un errore 4xx non viene ripetuto.
Altri endpoint dei webhook
| Endpoint | Metodo | Descrizione |
|---|---|---|
/webhooks | GET | Elenco dei webhook, con last_delivery_at e last_delivery_outcome. |
/webhooks/{webhook_id} | GET, PATCH, DELETE | Dettaglio, modifica (campi facoltativi), eliminazione (204). |
/webhooks/event-types | GET | Tipi di evento notificabili, con categoria ed esempio di data. |
/webhooks/{webhook_id}/deliveries | GET | Registro delle consegne: event_type, outcome (ok o failed), status_code, attempts, error_message, duration_ms, created_at. Filtro outcome, ordinamento sort_by (created_at, event_type, outcome, status_code, attempts, duration_ms) e sort_dir, paginazione. |
/webhooks/{webhook_id}/test | POST | Invia una notifica di prova. Risponde 202 ({ "status": "queued" }): l'esito compare nel registro delle consegne. |
/webhooks/generate-secret | POST | Genera un segreto casuale: { "secret": "..." }. |
Esempio di elemento di GET /webhooks/event-types:
{
"type": "document.uploaded",
"category": "documents",
"i18n_key": "admin.webhooks.events.documentUploaded",
"example_payload": {
"kb_id": "550e8400-e29b-41d4-a716-446655440000",
"document_id": "660e8400-e29b-41d4-a716-446655440001",
"filename": "report.pdf",
"size_bytes": 102400
}
}