Verifica accesso…
Integra Emma nelle tue applicazioni. Crea una chiave API, copiala e assicurati di avere credito disponibile.
Apri Prova Emma, inserisci la tua chiave API e seleziona il modello da utilizzare (Emma-6 o Emma-5). Scegli il formato della risposta, standard oppure JSON (disponibile esclusivamente con Emma-6), quindi inserisci la tua domanda.
Non è necessario creare un account: la pagina non memorizza la chiave API e mostra esclusivamente la risposta finale del modello. Ogni richiesta utilizza i crediti associati alla chiave API inserita.
La chiave deve appartenere allo stesso ambiente della pagina: per una chiave di produzione usa il link di produzione qui sopra, non il playground avviato su localhost.
Ogni richiesta include la chiave nell'header X-API-Key. L'api-key si ottiene dalla pagina Chiavi API ed è mostrata una sola volta. La stessa chiave vale per l'AI Generativa (Emma-6) e per il modello di classificazione dei prompt (Emma-Guardrails 1.0); una chiave assente, non valida, revocata o scaduta riceve 401.
X-API-Key: LA_TUA_API_KEY
| Endpoint | Uso | Chiave | Crediti |
|---|---|---|---|
POST https://emma.egomnia.com/api/chat/stream | generazione in streaming (sezioni 4–8) | sì | sì |
POST https://emma.egomnia.com/api/v1/guardrails/evaluate | controllo di sicurezza di un prompt, senza generazione (sezione 9) | sì | no |
GET https://emma.egomnia.com/api/models | modelli selezionabili: i valori di models[].key si usano in model_key | no | no |
Le richieste usano Content-Type application/json. La generazione risponde in application/x-ndjson (un evento JSON per riga); l'API Guardrails risponde con un singolo oggetto JSON.
Per POST /api/chat/stream solo message è obbligatorio. Campi principali:
| Campo | Tipo | Default | Note |
|---|---|---|---|
message | string | — | obbligatorio (1–4500 caratteri) |
model_key | string | emma-6 | modello da usare: emma-6 · emma-business · emma-5 · emma-4 · emma-3. L'elenco effettivo dipende dai modelli abilitati nel back office ed è in GET /api/models. Un modello indicato ma non disponibile riceve 409, senza ripiego su un altro modello. |
history | array | [] | turni conclusi {user, assistant}, al massimo 32; il server usa i più recenti entro il limite del modello (con Emma-6 quelli che entrano nei 4096 token di contesto) |
use_history | bool | false | true per usare la cronologia inviata |
use_rag | bool/null | null | recupero dal knowledge italiano; il kill-switch developer be:rag, seedato OFF, ha priorità assoluta. Solo quando è ON, il router può usare documenti e poi ricerca web automatica |
mode | string | raw | raw (fedele al modello) · assisted (ripulisce leggermente il messaggio) |
preset | string | balanced | precise (Focus) · balanced (Bilanciata) · creative (Creativa) · adaptive (Adattiva, sceglie i parametri dal tipo di messaggio) |
output_format | text | json | text | JSON esplicito con Emma-6; controlla la sintassi, non i valori. Leggere done.output_metadata.complete e syntax; un output parziale non è completato. |
max_new_tokens | int | — | tetto ai token generati (almeno 16). Senza, la risposta prosegue fino alla sua fine naturale o al limite del contesto |
temperature | float | dal preset | 0.10–1.50 |
top_p | float | dal preset | 0.10–1.00 |
top_k | int | dal preset | 1–256 |
repetition_penalty | float | dal preset | 1.00–2.00 |
seed | int | — | 0–4294967295: rende riproducibile la singola risposta |
I parametri numerici omessi prendono il valore del preset. Il server applica comunque i limiti del modello: con Emma-6 temperatura al massimo 1.30, top-k al massimo 200, repetition penalty almeno 1.04 e max_new_tokens al massimo 512.
Una sequenza di righe JSON (ndjson). Tipi di evento:
meta — informazioni iniziali: token del prompt, modello, preset e parametri effettivi.update — in content il testo generato fino a quel momento: ogni evento sostituisce il precedente, non è un delta.done — risposta finale in response, stats (con output_tokens) e il motivo dell'arresto in generation_metadata.stop_reason (per esempio eos, max_new_tokens, context_limit). Con output_format: "json" c'è anche output_metadata.error — errore durante la generazione, in message.Uno stream che si chiude senza done è interrotto: il testo ricevuto è parziale.
{"type": "meta", "prompt_tokens": 20, "mode": "raw", ...}
{"type": "update", "content": "Ciao"}
{"type": "update", "content": "Ciao, come"}
{"type": "done", "response": "Ciao, come stai?", "stats": {"output_tokens": 7, ...}, "generation_metadata": {"stop_reason": "eos", ...}}
curl
curl -N -X POST https://emma.egomnia.com/api/chat/stream \
-H "X-API-Key: LA_TUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message": "Ciao, chi sei?"}'
Python
import json, requests
resp = requests.post(
"https://emma.egomnia.com/api/chat/stream",
headers={"X-API-Key": "LA_TUA_API_KEY"},
json={"message": "Ciao, chi sei?"},
stream=True,
)
resp.raise_for_status() # 401, 402, 409, 422, 503: vedi la sezione 8
for line in resp.iter_lines():
if not line:
continue
event = json.loads(line)
if event["type"] == "update":
print(event["content"]) # testo completo generato finora
elif event["type"] == "done":
print("Risposta:", event["response"])
JavaScript (fetch)
const res = await fetch("https://emma.egomnia.com/api/chat/stream", {
method: "POST",
headers: { "X-API-Key": "LA_TUA_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ message: "Ciao, chi sei?" }),
});
if (!res.ok) throw new Error((await res.json()).detail?.code || res.status);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buf = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
const lines = buf.split("\n");
buf = lines.pop();
for (const line of lines) {
if (!line.trim()) continue;
const ev = JSON.parse(line);
if (ev.type === "update") console.log(ev.content); // testo completo finora
if (ev.type === "done") console.log("Risposta:", ev.response);
}
}
Le chiamate di generazione a POST /api/chat/stream consumano crediti in base ai token (input + output) e al listino corrente. I token di input sono quelli che il modello elabora davvero: con Emma-6 comprendono il suo system prompt, circa 95 token per richiesta. Con saldo esaurito la richiesta riceve 402; una richiesta respinta prima della generazione non consuma crediti. Il saldo è in Crediti; lo storico dei movimenti in Fatturazione.
La chat sul sito è gratuita. L'API Guardrails descritta sotto richiede una chiave per autenticarsi ma non genera token e non consuma crediti.
Gli errori di POST /api/chat/stream arrivano prima dello stream, come JSON con il campo detail; quando è un oggetto, detail.code identifica il caso. Un errore durante la generazione arriva invece come evento error.
| Codice | Significato |
|---|---|
401 | API key assente, non valida, revocata o scaduta |
402 | Saldo crediti esaurito |
409 | model_key non disponibile (disabilitato o non installato) |
422 | Corpo della richiesta non valido, oppure output_format: "json" con un modello che non lo supporta |
422 prompt_blocked | Il messaggio non ha superato Emma Guardrails: detail riporta category e category_description. Nessuna generazione e nessun addebito |
503 inference_capacity_reached | Capacità di generazione esaurita: riprova dopo i secondi indicati in Retry-After (2) |
503 guardrail_unavailable · guardrail_audit_unavailable | Il controllo di sicurezza non è disponibile e la richiesta non prosegue: riprova dopo Retry-After (30) |
Controlla un prompt con Emma Guardrails senza generare una risposta: è lo stesso classificatore che filtra ogni messaggio inviato a /api/chat/stream. La release è scelta dal server (oggi Emma-Guardrails 1.0) e v1 indica la versione del contratto, non del modello: non devi indicare né modello né parametri. La chiamata richiede la chiave ma non consuma crediti, non usa un modello generativo e non salva il prompt.
curl -X POST https://emma.egomnia.com/api/v1/guardrails/evaluate \
-H "X-API-Key: LA_TUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "Testo da controllare"}'
Richiesta
prompt: altri campi vengono rifiutati.unsafe perché l'intera richiesta sia unsafe, e un errore su qualunque segmento produce 503.Risposta
200 con un solo campo: {"decision": "safe"} oppure {"decision": "unsafe"}. Non vengono restituiti il prompt, la categoria, la confidenza o la versione del modello. Nella chat, invece, un messaggio unsafe riceve 422 prompt_blocked con la categoria (sezione 8).
| Verdetto | Categorie della release attuale (Emma-Guardrails 1.0) |
|---|---|
unsafe | Abuso sessuale su minori · Apologia e propaganda di ideologie estremiste · Attività illecite, armi, violenza e comportamenti lesivi · Avvelenamento e sostanze tossiche · Bestemmie e linguaggio blasfemo · Contenuti a sfondo sessuale · Contenuti discriminatori, stereotipati e d'odio · Domande a trabocchetto · Droghe e sostanze illecite · Identità di genere e orientamento sessuale · Opinioni e convinzioni personali · Prompt injection e manipolazione del modello · Utilizzo di linguaggio offensivo |
safe | Categoria non rilevata · Contenuti su religione, fede e spiritualità · Domande di attualità · Inserimento di dati personali · Presenza di nominativi · Presenza di personaggi pubblici · Proverbi, modi di dire, meme e umorismo italiano · Richieste di calcolo matematico |
Le categorie appartengono alla release e possono cambiare senza modifiche al contratto. Per vedere la categoria di un singolo prompt usa la pagina pubblica Emma Guardrails.
Errori
| Codice | Significato |
|---|---|
401 | API key assente, non valida, revocata o scaduta |
422 invalid_prompt | Body non valido, campi in più, prompt vuoto o oltre 100.000 caratteri. Il contenuto inviato non viene ripetuto nella risposta |
503 guardrail_unavailable | Controllo temporaneamente non disponibile: riprova dopo Retry-After (30). Non è un verdetto: decide la tua applicazione se bloccare o proseguire |
Python
import requests
resp = requests.post(
"https://emma.egomnia.com/api/v1/guardrails/evaluate",
headers={"X-API-Key": "LA_TUA_API_KEY"},
json={"prompt": "Testo da controllare"},
timeout=30,
)
if resp.status_code == 200:
print(resp.json()["decision"]) # "safe" oppure "unsafe"
elif resp.status_code == 503:
print("Riprova tra", resp.headers.get("Retry-After"), "secondi")
else:
print(resp.status_code, resp.json()["detail"])