Salta ai contenuti

Panoramica dell'API

Ogni endpoint REST di RolChat segue un unico contratto: lo stesso URL di base, lo stesso envelope della risposta, la stessa paginazione, la stessa forma degli errori. Lo impari una volta e ogni famiglia di endpoint nel riferimento degli endpoint si legge allo stesso modo.

https://api.rolchat.com/api/v1/

La versione è nel percorso. Aggiungere campi facoltativi, nuovi endpoint o nuovi parametri di query con valori predefiniti non è una modifica incompatibile e non fa avanzare la versione. Le modifiche incompatibili escono come v2, e gli endpoint v1 deprecati continuano a funzionare per almeno sei mesi dopo l’annuncio (vedi Deprecazione).

Metodo Intestazione Utilizzo
JWT bearer Authorization: Bearer <access_token> Sessioni interattive (app web, app mobile)
Chiave API Authorization: Bearer rcp_<secret> Chiamate machine-to-machine, chiavi API dei plugin
Firma HMAC X-RolChat-Signature: sha256=… Webhook in entrata dai tuoi sistemi, vedi Webhook
Nessuno - Endpoint pubblici del widget (/widget/…, /forms/…), limitati per sito e origine

Per le integrazioni usa una chiave API (un token di accesso personale). Le chiavi si creano in Impostazioni → Plugin → Chiavi API RolChat, vengono mostrate una sola volta e memorizzate solo come hash. Una chiave non può mai fare più del membro che l’ha creata: a ogni chiamata i suoi scope vengono confrontati con i permessi attuali di quel membro. Consulta Autenticazione per la durata dei JWT, l’intestazione X-Account-Id e le sessioni multi-azienda.

Una singola risorsa:

{
"data": { "id": "cnt_01HK…", "email": "ada@example.com" },
"meta": {
"request_id": "req_01HK…"
}
}

Un elenco:

{
"data": [ { … }, { … } ],
"meta": {
"request_id": "req_01HK…",
"count": 50,
"next_cursor": "cur_01HK…",
"prev_cursor": "cur_01HK…",
"has_more": true
}
}

Le risposte senza corpo (204 No Content dopo un’eliminazione) riportano comunque l’intestazione X-Request-Id.

Un errore:

{
"errors": [
{
"code": "validation_failed",
"message": "Email must be valid.",
"field": "email",
"details": { "received": "not-an-email" }
}
],
"meta": { "request_id": "req_01HK…" }
}

code è in snake_case leggibile dalle macchine ed è il valore su cui basare la logica; message è in inglese ed è pensato per i log. field e details sono presenti quando sono utili e non contengono mai dati personali. L’API non risponde mai 200 con un array errors: se ci sono errori lo stato è 400 o superiore. L’elenco completo dei codici si trova nella pagina Errori.

Gli endpoint di elenco che possono crescere usano la paginazione a cursore. Chiedi la prima pagina senza cursore, poi ripassa il next_cursor ricevuto, così com’è:

GET /api/v1/contacts?limit=50
GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…
  • limit vale 50 per impostazione predefinita ed è limitato a 200; i valori superiori vengono rifiutati con 400 validation_failed.
  • I cursori sono opachi e scadono dopo 24 ore (400 validation_failed con code: cursor_expired).
  • I risultati sono coerenti con lo snapshot scattato alla prima pagina: i record eliminati tra una pagina e l’altra scompaiono, i nuovi record compaiono solo quando ricominci senza cursore.
  • Per i client che la preferiscono viene inviata anche un’intestazione Link con rel="next" e rel="prev".

Invia un’intestazione Idempotency-Key (un UUID o ULID, fino a 255 caratteri) con qualsiasi POST, PATCH o DELETE:

  • La prima richiesta con una chiave viene eseguita e il suo stato e il suo corpo vengono conservati per 24 ore.
  • Una ripetizione con la stessa chiave e lo stesso corpo restituisce la risposta conservata senza rieseguire gli effetti collaterali.
  • Una ripetizione con la stessa chiave ma un corpo diverso viene rifiutata con 409 idempotency_key_conflict.

Usala per ogni chiamata che crea qualcosa con effetti collaterali: invio di un messaggio, di un’email o di un SMS, avvio di una chiamata, qualsiasi cosa venga fatturata. Le richieste GET sono sempre idempotenti e ignorano l’intestazione.

I limiti sono calcolati al minuto e riferiti all’account, alla chiave API o all’utente (all’indirizzo IP sulle route che non richiedono l’accesso). I valori massimi predefiniti:

Gruppo Limite predefinito Al minuto
Richieste senza accesso (per IP) 60 per IP
Utente autenticato (dashboard) 1 000 per utente
Chiave API 1 000 per chiave
Endpoint pubblici del widget 60 per visitatore e 600 per indirizzo di rete al minuto
Accesso (/auth/login) 5 per IP
Webhook in entrata 300 al minuto
Server MCP 600 al minuto
Endpoint OAuth 600 al minuto

I valori massimi sono quelli predefiniti della piattaforma e possono essere modificati dall’operatore; il tuo piano non li moltiplica e i limiti Enterprise sono concordati nel contratto. Gli endpoint con limiti di frequenza restituiscono:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 543

Quando superi un limite la risposta è 429 con code: rate_limited nell’array errors e un’intestazione Retry-After in secondi. Attendi quel tempo prima della chiamata successiva. Dieci accessi falliti bloccano l’account per 30 minuti.

Categoria Corpo massimo della richiesta Timeout del server
Predefinito 1 MB 30 s
Messaggio con allegati 25 MB 30 s
Importazione CSV 50 MB restituisce 202 ed è eseguita in background
Immagini della base di conoscenza 10 MB 30 s
API massiva 10 MB 30 s
Ricerca 1 MB 10 s
Richieste AI 1 MB 60 s
Endpoint del widget 100 KB 30 s

I corpi troppo grandi ricevono 413 payload_too_large. Un servizio a monte andato in timeout risponde 504 con code: upstream_timeout e un suggerimento retry_after quando ripetere può essere utile.

  • Richieste e risposte sono application/json; charset=utf-8. I caricamenti di file usano multipart/form-data; le esportazioni CSV restituiscono text/csv. L’UTF-8 non valido viene rifiutato con 400 validation_failed.
  • I timestamp sono in formato ISO-8601 in UTC con precisione al millisecondo: 2026-04-20T14:23:45.123Z. In input è accettato qualsiasi offset ISO-8601, normalizzato in UTC.
  • Gli identificatori sono ULID o UUID opachi. Non esistono ID numerici, e indirizzi email o numeri di telefono non compaiono mai in un URL.

Ogni richiesta autenticata viene eseguita all’interno di un account. Una risorsa che appartiene a un altro account, o a un sito non coperto dal ruolo del chiamante, risponde 404 not_found invece di 403, così l’esistenza dei record non trapela mai. Un token valido senza il permesso richiesto (per esempio contacts.delete) risponde 403 forbidden. Alcuni permessi hanno un suffisso di ambito (conversations.read:own, :team, :all) che restringe ciò che un elenco restituisce.

PATCH accetta solo campi scrivibili. id, account_id, created_at, updated_at e i campi di stato come resolved_at sono in sola lettura; inviarne uno restituisce 400 validation_failed con details.forbidden_fields. I cambi di stato passano da azioni dedicate come POST /tickets/:id/resolve.

Ogni scrittura viene registrata nel log di audit dell’account.

Ogni risposta riporta:

X-Request-Id: req_01HK…

Registra X-Request-Id nei log. È la prima cosa che chiede il supporto.

L’origine della dashboard nel browser è https://app.rolchat.com. Gli endpoint pubblici del widget accettano qualsiasi origine, oppure solo le origini che verifichi per un sito. Le chiamate server-to-server con una chiave API non sono soggette a CORS.

  1. La modifica viene annunciata nel changelog e l’endpoint interessato inizia a inviare Deprecation: true e un’intestazione Sunset con la data di rimozione.
  2. Gli endpoint pubblici continuano a funzionare per almeno sei mesi dopo l’annuncio.
  3. La rimozione avviene solo in una nuova versione major. All’interno di v1 le modifiche sono solo additive.

Ogni servizio espone /healthz (liveness) e /readyz (readiness).