Autenticazione
Le integrazioni si autenticano presso le API di Askme AI con una chiave API. Ogni richiesta deve contenere una chiave valida nell'intestazione X-Api-Key; la chiave identifica l'organizzazione e stabilisce, tramite i suoi scope, quali operazioni sono consentite.
Generazione della chiave API
Le chiavi si generano dalla console della propria organizzazione:
- Accedere alla console con un utente amministratore.
- Aprire Impostazioni › Chiavi API e selezionare Nuova chiave.
- Indicare un nome descrittivo (per esempio
integrazione-crm-prod), l'applicazione di origine, le Funzioni della chiave (gli scope) ed eventualmente i limiti di frequenza e una scadenza. - Selezionare Crea e copiare il valore mostrato nel dialog Chiave API generata: viene presentato una sola volta e, dopo la chiusura del dialog, non è più recuperabile.
La procedura completa, con le schermate, è descritta nel manuale.
Una chiave API dà accesso ai dati dell'organizzazione. Va conservata in un archivio di segreti (HashiCorp Vault, AWS Secrets Manager, variabili d'ambiente cifrate) e non deve essere inclusa nei repository di codice né nel codice eseguito dal browser.
Formato della chiave
Tutte le chiavi hanno il prefisso amai_ seguito da una stringa opaca:
amai_3f9d8c1e0a4b2f7d6c5a8e9b3f1d2c4a8e9b3f1d2c4a8e9b
Nelle interfacce di gestione e nei log compare soltanto la parte iniziale della chiave (key_prefix), sufficiente a riconoscerla senza esporne il valore.
Intestazione di autenticazione
Ogni richiesta alle API REST deve includere:
X-Api-Key: amai_<chiave>
Esempio cURL
curl "https://ai.askme.it/api/v2/agents" \
-H "X-Api-Key: amai_3f9d8c1e0a4b2f7d6c5a8e9b3f1d2c4a8e9b3f1d2c4a8e9b"
Esempio Python (httpx)
import os
import httpx
client = httpx.Client(
base_url="https://ai.askme.it/api/v2",
headers={"X-Api-Key": os.environ["ASKMEAI_API_KEY"]},
timeout=30.0,
)
resp = client.get("/agents")
resp.raise_for_status()
print(resp.json())
Esempio Node.js (fetch)
const API_KEY = process.env.ASKMEAI_API_KEY;
const BASE = 'https://ai.askme.it/api/v2';
const resp = await fetch(`${BASE}/agents`, {
headers: { 'X-Api-Key': API_KEY },
});
if (!resp.ok) {
throw new Error(`API error ${resp.status}: ${await resp.text()}`);
}
const data = await resp.json();
console.log(data);
Intestazioni
| Intestazione | Obbligatoria | Descrizione |
|---|---|---|
X-Api-Key | Sì | Chiave nel formato amai_<chiave> |
Content-Type | Sui corpi JSON | application/json sulle richieste POST, PUT e PATCH con corpo JSON |
X-Source-App | No | Applicazione a cui attribuire consumi e conversazioni (vedere sotto) |
X-External-Id | No | Identificativo opaco del sistema esterno (numero di ticket, di ordine, ...), riportato in ogni record di consumo prodotto dalla richiesta. Massimo 255 caratteri |
Attribuzione con X-Source-App
L'intestazione X-Source-App stabilisce a quale applicazione vengono attribuiti i consumi e le conversazioni generati dalla richiesta. È facoltativa: se manca, oppure se il valore non è tra quelli riconosciuti dalla piattaforma, la richiesta viene attribuita all'applicazione di origine impostata sulla chiave al momento della creazione. Un valore non riconosciuto non provoca un errore.
| Valore | Quando usarlo |
|---|---|
api_direct | Integrazione del cliente che chiama direttamente le API REST (valore consigliato) |
askmechat | Chiamate provenienti da Askme Chat |
askmedesk | Chiamate provenienti da Askme Desk |
askmesign | Chiamate provenienti da Askme Sign |
La piattaforma riconosce anche altri valori riservati alle proprie applicazioni e ai servizi interni, che un'integrazione non deve usare. Si consiglia di mantenere lo stesso valore per tutta l'integrazione, così che i consumi siano leggibili in modo coerente nella console.
Esempio di richiesta completa
curl -X POST "https://ai.askme.it/api/v2/chat" \
-H "X-Api-Key: amai_3f9d8c1e..." \
-H "Content-Type: application/json" \
-H "X-Source-App: api_direct" \
-H "X-External-Id: ticket-92831" \
-d '{
"agent_id": 12,
"message": "Come si effettua un reso?",
"stream": false
}'
Per ricevere la risposta in streaming (SSE) si imposta "stream": true nel corpo: l'endpoint resta POST /api/v2/chat e risponde con Content-Type: text/event-stream.
Permessi e scope
Ogni chiave porta un elenco di scope, che stabilisce quali operazioni la chiave può eseguire. Nella console gli scope corrispondono alle Funzioni della chiave.
Il valore predefinito è *, che copre tutte le funzioni di prodotto dell'organizzazione: agenti, chat e conversazioni, basi di conoscenza, analisi, connettori e webhook, impostazioni dell'organizzazione e registro di audit. Restano escluse la gestione di utenti, ruoli e chiavi API, che richiede scope espliciti (per esempio admin.api_keys.create), e le funzioni riservate alla piattaforma, che nessuna chiave può ottenere.
Uno scope può indicare un permesso in tre modi:
| Forma | Esempio | Copre |
|---|---|---|
| Codice completo | knowledge_bases.read | Solo quel permesso |
| Parte finale del codice | api_keys.create | admin.api_keys.create |
Prefisso seguito da .* | agents.* | Tutti i permessi che iniziano con agents. |
Alla creazione e alla modifica di una chiave, uno scope che non corrisponde ad alcun permesso assegnabile viene rifiutato con 422; il corpo della risposta riporta gli scope non accettati:
{
"detail": {
"code": "API_KEY_SCOPES_REJECTED",
"message": "Scopes that cannot be assigned to an API key: agenti.leggi. A scope must name at least one existing permission code and no super_admin.* code.",
"rejected_scopes": ["agenti.leggi"]
}
}
L'elenco dei codici assegnabili, insieme ai prefissi che * non copre, è restituito da GET /api/v2/api-keys/scopes (si veda Endpoint: Utenti, Organizzazione e Quote).
Il ruolo che si può ancora associare a una chiave tramite API non concede permessi: una chiave può fare soltanto ciò che i suoi scope coprono, e una chiave senza scope non può eseguire operazioni protette. Per integrazioni con esigenze diverse si consiglia di creare chiavi separate, ciascuna con gli scope minimi necessari; per un'applicazione che si limita a conversare con un agente, per esempio, sono sufficienti gli scope di consultazione degli agenti e di avvio delle conversazioni.
Fino alla versione 2.1 lo scope * copriva anche la gestione di utenti, ruoli e chiavi API. Dalla versione 2.2 non è più così: un'integrazione che crea utenti, assegna ruoli o gestisce chiavi con una chiave * riceve 403. Per ripristinare queste operazioni occorre aggiungere alla chiave gli scope espliciti corrispondenti (per esempio admin.users.create, admin.roles.update, admin.api_keys.read).
Una chiave API non riceve mai le fonti nascoste delle basi di conoscenza: le risposte della chat e i messaggi letti tramite API contengono soltanto le fonti visibili, indipendentemente dagli scope.
Organizzazione
L'intestazione X-Tenant-ID non è richiesta: l'organizzazione è determinata dalla chiave, che le appartiene dal momento della generazione.
Errori di autenticazione e autorizzazione
| Codice HTTP | Causa tipica |
|---|---|
401 Unauthorized | Intestazione X-Api-Key assente, valore incompleto o senza prefisso amai_, chiave revocata o scaduta |
403 Forbidden con code: PERMISSION_DENIED | Gli scope della chiave non coprono il permesso indicato nel campo permission |
403 Forbidden con code: FEATURE_FLAG_DISABLED | La funzionalità indicata nel campo flag non è attiva per l'organizzazione |
429 Too Many Requests con Retry-After | Limite di frequenza della chiave superato |
429 Too Many Requests senza Retry-After | Quota del piano esaurita |
Il testo del messaggio di un 401 può variare tra i servizi (per esempio Missing authentication token oppure Invalid API key): conviene basare la gestione degli errori sul codice HTTP. Esempio di 403:
{
"detail": {
"code": "PERMISSION_DENIED",
"permission": "knowledge_bases.delete"
}
}
Limiti di frequenza
Ogni chiave può avere limiti dedicati:
rate_limit_rpm: richieste al minuto;rate_limit_rpd: richieste al giorno.
Un limite non impostato non limita la chiave. I limiti valgono per la singola chiave in tutti i servizi che accettano chiavi API. Quando un limite è raggiunto il servizio risponde 429 con l'intestazione Retry-After, che indica i secondi da attendere prima di ripetere la richiesta.
Rotazione e revoca
- Rotazione: operazione atomica che revoca la chiave esistente e ne crea una sostitutiva con le stesse impostazioni (nome, scope, limiti; la scadenza, se presente, riparte dalla rotazione con la stessa durata). Il nuovo valore viene mostrato una sola volta. Una chiave revocata o scaduta non si può ruotare: la richiesta risponde
409. - Revoca: disattiva immediatamente la chiave. È un'operazione irreversibile.
Nome, scope, limiti di frequenza e scadenza di una chiave attiva si possono modificare senza rigenerarla.
Buone pratiche
- Usare una chiave distinta per ogni integrazione e per ogni ambiente.
- Assegnare a ogni chiave i soli scope necessari, invece di
*. - Impostare una scadenza realistica (per esempio 90 o 180 giorni) e pianificare la rotazione.
- Inviare lo stesso
X-Source-Appper tutta l'integrazione, così che i consumi siano riconoscibili nella sezione Monitoraggio della console. - In caso di sospetta compromissione, revocare subito la chiave e verificare gli accessi nel Registro attività della console.