API REST v1
Gestisca agenti, legga conversazioni e contatti e chatti dal suo backend, con semplice HTTP.
curl https://api.onetype.ai/v1/agents -H "Authorization: Bearer sk_live_…"Autenticazione e chiavi
Crei le chiavi in Developer › API keys (proprietario o amministratore). Una chiave viene mostrata una sola volta.
| Chiave | Prefisso | Uso | Può fare |
|---|---|---|---|
| Secret | sk_live_ | Solo i suoi server | Tutto ciò che può fare un amministratore del workspace, tranne le azioni di identità e di proprietà |
| Restricted | rk_live_ | Server, CI, strumenti di automazione | Solo le autorizzazioni che seleziona alla creazione (mai più delle sue) |
Le chiavi API sono incluse con Premium. Invii la chiave come Authorization: Bearer <key>. Le chiavi appartengono a un solo workspace e una chiave non può mai leggere i dati di un altro workspace. Tenga le chiavi secret e restricted fuori da browser, app mobili e repository. Se una chiave trapela, la revochi nella dashboard e la richiesta successiva con essa fallisce.
Risorse
| Endpoint | Scope (autorizzazione) | Stato |
|---|---|---|
GET/POST /v1/agents, GET/PATCH/DELETE /v1/agents/:id | agents.read, agents.update, … | Disponibile |
GET /v1/conversations?agent&status&created[gte], GET /v1/conversations/:id, GET /v1/conversations/:id/messages | conversations.read | Disponibile |
POST /v1/conversations { agent } | conversations.write (solo chiavi) | Disponibile |
POST /v1/conversations/:id/messages { content, stream? } | conversations.write | Disponibile |
GET /v1/contacts?agent, GET /v1/contacts/:id | contacts.read | Disponibile |
POST/DELETE /v1/mcp, /v1/mcp/agents/:agent | vedere MCP | Disponibile |
La conoscenza e l'utilizzo si gestiscono nella dashboard.
Un contatto appartiene a un solo agente (agent, un id agt_… ): la stessa persona sui siti di due dei suoi agenti corrisponde a due contatti. ?agent=agt_… elenca quelli di un agente.
Gli oggetti pubblici usano campi snake_case e id con prefisso (le route dei visitatori di una chat personalizzata usano camelCase, per esempio isAiGenerated; snake_case, is_ai_generated, esiste solo nelle strutture /v1 ). Non contengono mai campi interni. Ogni oggetto messaggio ha is_ai_generated (true per le risposte dell'agente, false per quelle del suo team), come richiede il Regolamento UE sull'IA (AI Act).
OpenAPI: https://api.onetype.ai/v1/openapi.json, generato dagli stessi schemi con cui l'API convalida.
Stati delle conversazioni
Gli oggetti conversazione (in /v1 e nei webhook conversation.* ) contengono status e, quando risolta, resolved_by:
status | Significato |
|---|---|
open | In corso |
escalated | Passata al suo team; solo una persona la chiude |
resolved | Chiusa con una risposta. resolved_by: ai (chiusa automaticamente dopo una buona risposta), member (una persona del suo team), visitor (confermata dal visitatore) oppure idle (conversazioni chiuse prima del 2026-09-24) |
unresolved | Chiusa automaticamente dopo che l'ultima risposta dell'agente ha dichiarato di non sapere, o è stata valutata negativamente. Torna a open se il visitatore scrive di nuovo |
failed | Non ha potuto ricevere risposta a causa di un errore, oppure è stata chiusa dal suo team come non risolta (anche dopo un passaggio a un operatore) |
Una conversazione gestita dal solo agente si chiude automaticamente 30 minuti dopo l'ultimo messaggio. Le conversazioni con passaggio a un operatore, gestite dal suo team o in attesa di un messaggio del visitatore senza risposta non vengono mai chiuse automaticamente. Possono essere aggiunti nuovi valori; tratti quelli sconosciuti come open.
Paginazione
Gli endpoint di elenco usano i cursori:
curl "https://api.onetype.ai/v1/conversations?limit=50" -H "Authorization: Bearer sk_live_…"{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "b3BhcXVl…" }Passi cursor=<next_cursor> per la pagina successiva. limit è 20 per impostazione predefinita, con un massimo di 100. I cursori sono opachi e restano stabili quando arrivano nuovi elementi mentre scorre le pagine.
Idempotenza
Invii Idempotency-Key: <any unique string> su qualsiasi POST per rendere sicuri i nuovi tentativi. Il primo risultato viene conservato per 24 ore, e un nuovo tentativo con la stessa chiave lo restituisce invece di rifare il lavoro.
curl -X POST https://api.onetype.ai/v1/conversations \
-H "Authorization: Bearer sk_live_…" \
-H "Idempotency-Key: 6f1c9f2e-3b1d-4a0e-9d0f-2f6f0b3c9a11" \
-H "Content-Type: application/json" \
-d '{"agent":"YOUR_AGENT_ID"}'- Una risposta riproposta contiene
Idempotent-Replayed: true. - Le chiavi sono 1–255 caratteri ASCII stampabili. Qualsiasi altra cosa è
400 BAD_IDEMPOTENCY_KEY. - La stessa chiave con un corpo diverso è
409 IDEMPOTENCY_KEY_REUSED. Usi una nuova chiave per una nuova richiesta. - Finché la prima richiesta con una chiave è ancora in corso, un nuovo tentativo riceve
409 IDEMPOTENCY_KEY_IN_USE. Attenda e riprovi. - Gli errori di convalida non vengono memorizzati (corregga la richiesta e riprovi con la stessa chiave). Un rifiuto prodotto dal lavoro stesso (per esempio un limite del piano) viene memorizzato e riproposto.
- Le chiavi sono private per il suo workspace e la sua chiave.
Errori
Ogni errore ha la stessa struttura, più un'intestazione x-request-id . Includa l'id della richiesta quando contatta l'assistenza.
{ "error": { "status": 422, "code": "VALIDATION_FAILED", "message": "content: required", "fields": { "content": "Required" } } }| Stato | Quando | Codici tipici |
|---|---|---|
| 400 | La richiesta non è valida | VALIDATION_FAILED (vedere fields), BAD_IDEMPOTENCY_KEY |
| 401 | La chiave manca, è errata o è stata revocata | UNAUTHENTICATED |
| 403 | La chiave non ha l'autorizzazione | PERMISSION_DENIED |
| 404 | Non trovato nel suo workspace (gli oggetti di altri workspace appaiono come inesistenti) | NOT_FOUND |
| 409 | Conflitti | IDEMPOTENCY_KEY_REUSED, IDEMPOTENCY_KEY_IN_USE, INVALID_TRANSITION |
| 402 / 422 | Limiti del piano e regole di business | QUOTA_EXCEEDED, REFUSED (il messaggio ne spiega il motivo) |
| 429 | Troppe richieste | RATE_LIMITED |
| 5xx | Colpa nostra | sempre INTERNAL, con l'id della richiesta. Se continua a succedere, scriva a support@onetype.ai con l'id della richiesta |
code i valori sono stabili. Basi la gestione su di essi, non su message.
Limiti di frequenza
Per chiave: 100 richieste ogni 10 secondi e 20 messaggi di chat ogni 10 secondi. Limiti più alti sono inclusi nei piani superiori. Ogni risposta contiene:
RateLimit-Limit: 100
RateLimit-Remaining: 87
RateLimit-Reset: 6Una 429 contiene anche Retry-After (secondi). Attenda tanto, poi riprovi. Non riprovi in un ciclo serrato.
L'autenticazione fallita è limitata per indirizzo di rete. Le richieste con una chiave errata o revocata contano sull'indirizzo da cui provengono. Se molti client condividono un indirizzo pubblico (un NAT aziendale, un provider di CI), un solo client configurato male può esaurire il limite, e allora anche le richieste con una chiave valida da quell'indirizzo ricevono 429 RATE_LIMITED finché la finestra non si azzera. Lo gestisca come qualsiasi 429: rispetti Retry-After, poi corregga il client che invia la chiave errata.
async function call(url: string, init: RequestInit, attempts = 3): Promise<Response>
{
const response = await fetch(url, init);
if (response.status !== 429 || attempts <= 1)
{
return response;
}
const waitSeconds = Number(response.headers.get("retry-after") ?? "1");
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
return call(url, init, attempts - 1);
}Chat dal suo backend
Crei una conversazione per un agente, poi vi invii dei messaggi. Ogni risposta viene scritta, memorizzata e fatturata esattamente come una risposta del widget.
curl -X POST https://api.onetype.ai/v1/conversations \
-H "Authorization: Bearer sk_live_…" -H "Content-Type: application/json" \
-d '{"agent":"YOUR_AGENT_ID"}'
# → { "id": "cnv_…", "object": "conversation", "status": "open", … }
curl -X POST https://api.onetype.ai/v1/conversations/cnv_…/messages \
-H "Authorization: Bearer sk_live_…" -H "Idempotency-Key: order-1234-question-1" -H "Content-Type: application/json" \
-d '{"content":"Where is order 1234?"}'
# → { "id": "msg_…", "object": "message", "role": "assistant", "is_ai_generated": true, "parts": [ … ], … }Il campo parts della risposta contiene parti text e una parte source-document per ogni fonte citata (title e url per le pagine web).
Streaming
Invii "stream": true per ricevere la risposta mentre viene scritta, come eventi inviati dal server nel formato AI SDK UI Message Stream v1 . La risposta contiene x-vercel-ai-ui-message-stream: v1, e il campo data di ogni evento è una parte JSON: start, text-start, text-delta (con delta), text-end, source-document, finish (con messageMetadata.outcome), error oppure abort. Lo stream termina con data: [DONE].
const response = await fetch(`https://api.onetype.ai/v1/conversations/${conversationId}/messages`, {
method: "POST",
headers: { "Authorization": `Bearer ${process.env.ONETYPE_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({ content: "How do refunds work?", stream: true }),
});
const reader = response.body!.pipeThrough(new TextDecoderStream()).getReader();
let buffer = "";
for (;;)
{
const { value, done } = await reader.read();
if (done) break;
buffer += value;
const events = buffer.split("\n\n");
buffer = events.pop() ?? "";
for (const event of events)
{
const data = event.split("\n").find((line) => line.startsWith("data: "))?.slice(6);
if (data === undefined || data === "[DONE]") continue;
const part = JSON.parse(data);
if (part.type === "text-delta") process.stdout.write(part.delta);
if (part.type === "source-document") console.log(`\n[source] ${part.title}`);
}
}Con il Vercel AI SDK sul suo server può passare la risposta direttamente a useChat, perché è lo stesso formato.
- Disconnettersi non annulla la risposta. La risposta viene comunque scritta, memorizzata e fatturata.
- Riprovare uno stream terminato è sicuro. Riprovi con la stessa
Idempotency-Keye otterrà la risposta memorizzata come JSON (stato 200), non una seconda risposta.
Versionamento
/v1 cambia solo in modo additivo: nuovi campi, nuovi endpoint, nuovi tipi di evento. Il suo codice deve ignorare i campi che non conosce. Se mai servisse una modifica non retrocompatibile, uscirà come nuova versione selezionata per chiave, con preavviso.