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.
URL di base e versioning
Sezione intitolata “URL di base e versioning”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).
Autenticazione
Sezione intitolata “Autenticazione”| 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.
Envelope della risposta
Sezione intitolata “Envelope della risposta”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.
Paginazione
Sezione intitolata “Paginazione”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=50GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…limitvale 50 per impostazione predefinita ed è limitato a 200; i valori superiori vengono rifiutati con400 validation_failed.- I cursori sono opachi e scadono dopo 24 ore (
400 validation_failedconcode: 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
Linkconrel="next"erel="prev".
Idempotenza
Sezione intitolata “Idempotenza”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.
Limiti di frequenza
Sezione intitolata “Limiti di frequenza”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: 1000X-RateLimit-Remaining: 543Quando 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.
Dimensioni e timeout
Sezione intitolata “Dimensioni e timeout”| 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.
Tipi di contenuto, date e ID
Sezione intitolata “Tipi di contenuto, date e ID”- Richieste e risposte sono
application/json; charset=utf-8. I caricamenti di file usanomultipart/form-data; le esportazioni CSV restituisconotext/csv. L’UTF-8 non valido viene rifiutato con400 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.
Isolamento dei tenant e permessi
Sezione intitolata “Isolamento dei tenant e permessi”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.
Intestazioni di osservabilità
Sezione intitolata “Intestazioni di osservabilità”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.
Deprecazione
Sezione intitolata “Deprecazione”- La modifica viene annunciata nel changelog e l’endpoint interessato inizia a inviare
Deprecation: truee un’intestazioneSunsetcon la data di rimozione. - Gli endpoint pubblici continuano a funzionare per almeno sei mesi dopo l’annuncio.
- La rimozione avviene solo in una nuova versione major. All’interno di
v1le modifiche sono solo additive.
Stato di salute
Sezione intitolata “Stato di salute”Ogni servizio espone /healthz (liveness) e /readyz (readiness).