API reference
JSON garantito e chiamata di funzioni
Imporre il formato della risposta invece di sperarci: response_format, json_schema e tools. Per chi estrae campi da documenti.
Last updated: 2026-08-16
Risposte in JSON e chiamata di funzioni
Se dovete estrarre campi da un documento e riversarli in un gestionale, questa è la pagina che vi serve. Non dovete scrivere un parser tollerante e non dovete sperare che il modello risponda nel formato giusto: lo si impone.
Entrambe le funzioni sono attive su tutti i modelli di conversazione del catalogo e seguono la stessa forma dell'interfaccia di OpenAI, quindi funzionano con le librerie che usate già.
JSON garantito
Con response_format il motore vincola la generazione: la risposta è JSON
valido, non «di solito» JSON valido.
curl https://api.siati.ai/v1/chat/completions \
-H "Authorization: Bearer $SIATI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-4-26b",
"messages": [{"role": "user", "content": "Estrai i campi da questa fattura: ..."}],
"response_format": {"type": "json_object"}
}'
Con uno schema, se volete anche i campi giusti
json_object garantisce che sia JSON. Se volete garantire quali chiavi ci
sono e di che tipo, passate lo schema:
{
"model": "gemma-4-26b",
"messages": [{"role": "user", "content": "…"}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "fattura",
"schema": {
"type": "object",
"properties": {
"numero_documento": {"type": "string"},
"data": {"type": "string"},
"totale": {"type": "number"},
"aliquota_iva": {"type": "number"}
},
"required": ["numero_documento", "data", "totale"]
}
}
}
}
Il modello non può produrre un documento che non rispetti lo schema. Le chiavi richieste ci sono sempre, e i tipi sono quelli dichiarati.
Chiamata di funzioni
Passate tools e il modello risponde con tool_calls invece che con del
testo, esattamente come con l'interfaccia di OpenAI.
{
"model": "gemma-4-26b",
"messages": [{"role": "user", "content": "Registra la fattura 2026-114 da 1'250 franchi"}],
"tools": [{
"type": "function",
"function": {
"name": "registra_fattura",
"description": "Crea una bozza di fattura fornitore",
"parameters": {
"type": "object",
"properties": {
"numero": {"type": "string"},
"importo": {"type": "number"}
},
"required": ["numero", "importo"]
}
}
}]
}
La risposta contiene choices[0].message.tool_calls, con function.name e
function.arguments come stringa JSON.
Fino a quando non funzionava
Dal 16 al 18 agosto 2026 il gateway non inoltrava response_format al
motore: chi lo passava riceveva prosa libera, o un oggetto avvolto in un
recinto markdown, e questa pagina prometteva il contrario. Corretto il 18
agosto. Se avete scritto una validazione a valle per aggirarlo, potete
tenerla — non fa male — ma non vi serve più.
Con stream: true il difetto è durato due giorni in più: il formato veniva
inoltrato sul percorso normale e non su quello a pezzi, quindi chi chiedeva JSON
in streaming riceveva ancora prosa. Corretto anche quello il 18 agosto; adesso
response_format vale su entrambe le strade.
Nello stesso giro è stato corretto tool_choice: "required", che rispondeva
502. La causa non era il valore: era che un "properties": {} nello schema
arrivava al motore come [], e il motore rifiutava la grammatica.
Quello che non garantiamo, e va detto
I numeri restano da ricalcolare. Il modello legge bene, ma un totale letto non è un totale verificato: sommate le righe e confrontate. Vale per qualunque modello, non solo per i nostri, ed è il motivo per cui il risultato dovrebbe sempre finire in una bozza da confermare e mai direttamente a giornale.
Lo schema vincola la forma, non la verità. Se il campo data è richiesto,
nella risposta c'è; che sia la data giusta lo dice il vostro controllo, non noi.
Gli enum dentro tools non sono vincolati. Nello schema di
response_format sì; nei parametri di una funzione no, perché lì il vincolo
non passa dalla grammatica. Il modello tende a rispondere con la parola
italiana: "urgente" invece di "urgent". Due cose che funzionano, e ce le ha
insegnate chi integra: mettere la mappatura nella description della proprietà
(«urgente/urgentissimo=urgent, alta=high») alza molto l'aderenza, e validare a
valle resta necessario.
Il modello a volte scrive la stringa "null". Su un campo che ammette
null, invece del valore JSON può arrivare la parola di quattro lettere. Chi
integra dovrebbe trattare "null", "none", "nessuno" e la stringa vuota
come assenza.
Su una fattura svizzera, leggete prima il codice QR. Se il documento ha la sezione di pagamento con il codice, IBAN, riferimento, importo e creditore si leggono in modo deterministico, senza modello e senza margine di errore. Usate il modello per quello che il codice non contiene: numero del documento, date, righe, aliquote. È l'ordine giusto, e vi costa meno.
Ricerca sui vostri documenti
La ricerca sull'archivio (caricate i documenti, fate una domanda, ottenete la risposta con il passaggio da cui viene) non è attiva in questo momento: l'archivio vettoriale non è in servizio. Se il vostro caso è l'estrazione di campi da fatture non vi serve — bastano le due funzioni qui sopra.
Se invece vi serve, scriveteci: è la richiesta che ne deciderebbe la priorità.