Verifica accesso…

Documentazione API

Integra Emma nelle tue applicazioni. Crea una chiave API, copiala e assicurati di avere credito disponibile.

1. Prova senza scrivere codice

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.

2. Autenticazione

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

3. Endpoint

EndpointUsoChiaveCrediti
POST https://emma.egomnia.com/api/chat/streamgenerazione in streaming (sezioni 4–8)sìsì
POST https://emma.egomnia.com/api/v1/guardrails/evaluatecontrollo di sicurezza di un prompt, senza generazione (sezione 9)sìno
GET https://emma.egomnia.com/api/modelsmodelli selezionabili: i valori di models[].key si usano in model_keynono

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.

4. Corpo della richiesta

Per POST /api/chat/stream solo message è obbligatorio. Campi principali:

CampoTipoDefaultNote
messagestring—obbligatorio (1–4500 caratteri)
model_keystringemma-6modello 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.
historyarray[]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_historyboolfalsetrue per usare la cronologia inviata
use_ragbool/nullnullrecupero 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
modestringrawraw (fedele al modello) · assisted (ripulisce leggermente il messaggio)
presetstringbalancedprecise (Focus) · balanced (Bilanciata) · creative (Creativa) · adaptive (Adattiva, sceglie i parametri dal tipo di messaggio)
output_formattext | jsontextJSON esplicito con Emma-6; controlla la sintassi, non i valori. Leggere done.output_metadata.complete e syntax; un output parziale non è completato.
max_new_tokensint—tetto ai token generati (almeno 16). Senza, la risposta prosegue fino alla sua fine naturale o al limite del contesto
temperaturefloatdal preset0.10–1.50
top_pfloatdal preset0.10–1.00
top_kintdal preset1–256
repetition_penaltyfloatdal preset1.00–2.00
seedint—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.

5. Risposta in streaming

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", ...}}

6. Esempi

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);
  }
}

7. Crediti e costi

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.

8. Errori

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.

CodiceSignificato
401API key assente, non valida, revocata o scaduta
402Saldo crediti esaurito
409model_key non disponibile (disabilitato o non installato)
422Corpo della richiesta non valido, oppure output_format: "json" con un modello che non lo supporta
422 prompt_blockedIl messaggio non ha superato Emma Guardrails: detail riporta category e category_description. Nessuna generazione e nessun addebito
503 inference_capacity_reachedCapacità di generazione esaurita: riprova dopo i secondi indicati in Retry-After (2)
503 guardrail_unavailable · guardrail_audit_unavailableIl controllo di sicurezza non è disponibile e la richiesta non prosegue: riprova dopo Retry-After (30)

9. API Guardrails

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

  • Il body contiene solo prompt: altri campi vengono rifiutati.
  • Il testo viene ripulito dagli spazi ai bordi e deve avere da 1 a 100.000 caratteri.
  • I testi più lunghi della finestra del modello (5.000 caratteri con la release attuale) vengono divisi in segmenti: basta un segmento 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).

VerdettoCategorie della release attuale (Emma-Guardrails 1.0)
unsafeAbuso 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
safeCategoria 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

CodiceSignificato
401API key assente, non valida, revocata o scaduta
422 invalid_promptBody non valido, campi in più, prompt vuoto o oltre 100.000 caratteri. Il contenuto inviato non viene ripetuto nella risposta
503 guardrail_unavailableControllo 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"])