API pubblica
L'helpdesk espone una sola API pubblica: un endpoint GraphQL. Ogni operazione dello schema è raggiungibile fuori dal browser con un token di accesso personale (Personal Access Token, PAT).
Questa pagina è il contratto: che cosa è stabile, come autenticarsi, che cosa concedono gli ambiti e come sono strutturati gli errori. La CLI hdmx è costruita su di essa, e il versionamento dell'API descrive come evolve questa superficie.
L'endpoint
POST https://<your-host>/backend/<subdomain>/api/<version>/graphql
<subdomain>identifica il tuo account (lo stesso identificativo con cui accedi).<version>è una versione datata dell'API, ad esempio2026-07— vedi versionamento dell'API. Puoi anche omettere il segmento della versione e chiamare…/backend/<subdomain>/graphql; la richiesta viene allora servita dalla versione più vecchia supportata e ogni risposta ti dice quale versione ha risposto.
Autenticazione
Invia un token di accesso personale come credenziale Bearer:
Authorization: Bearer hdmx_<random>
Un PAT è a lunga durata (con scadenza obbligatoria), dotato di ambiti, limitato per IP e revocabile. È legato a un solo account: presentare un token al sottodominio di un altro account viene rifiutato con HTTP 401.
Creare un token
Crea e gestisci i token tu stesso nell'app agente, in Settings → API tokens:
- Fai clic su New token.
- Dagli un nome che riconoscerai in seguito.
- Scegli una scadenza (fino a 365 giorni: non esiste l'opzione «mai»).
- Imposta una politica di accesso: attiva esattamente le risorse di cui questo token ha bisogno, in lettura o in lettura e scrittura. Per impostazione predefinita non c'è alcun accesso.
- Aggiungi almeno un indirizzo IP o CIDR all'elenco consentito (obbligatorio — vedi Elenco IP consentiti). Il modulo può inserire per te il tuo IP attuale.
- Controlla e crea. Il token completo viene mostrato esattamente una volta: copialo subito. Viene memorizzato solo un hash, quindi non potrà mai essere mostrato di nuovo; se lo perdi, ruota il token per ottenerne uno nuovo.
In seguito puoi modificare la politica di accesso e l'elenco consentito di un token, ruotarlo (emettere un nuovo segreto mentre il vecchio continua a funzionare per un breve periodo di grazia, così da passare senza interruzioni) e revocarlo. Ogni token mostra quando e da dove è stato usato l'ultima volta, oltre a un registro dell'attività recente.
Ambiti
L'accesso è a grana grossa e organizzato per famiglie di risorse. Un token porta un insieme fisso di ambiti; ogni operazione di primo livello ne verifica uno.
| Ambito | Concede |
|---|---|
tickets:read | Leggere ticket, messaggi, bozze, cronologia, allegati, report |
tickets:write | Creare / aggiornare / eliminare ticket, pubblicare messaggi, caricare allegati. Implica tickets:read |
chat:read | Leggere chat, conversazioni, messaggi, sessioni |
chat:write | Inviare messaggi dell'agente, entrare / uscire / chiudere / riaprire conversazioni. Implica chat:read |
customers:read | Leggere le schede clienti |
customers:write | Creare / aggiornare / unire schede clienti. Implica customers:read |
settings:read | Leggere le impostazioni dell'account (reparti, stati, priorità, caselle di posta — senza segreti) |
I campi delle credenziali delle caselle di posta (nomi utente, password e host IMAP/SMTP) non vengono mai restituiti a un token, qualunque sia l'ambito: quei segreti appartengono al tuo provider di posta e restano fuori dalla portata dell'API pubblica.
Tassonomia degli errori
Le risposte GraphQL usano errors[].extensions.code:
| Codice | Significato | HTTP |
|---|---|---|
SCOPE_DENIED | Al token manca l'ambito richiesto. extensions.valid_values elenca gli ambiti che soddisferebbero l'operazione | 200 |
RATE_LIMITED | Il budget di richieste per token è esaurito. extensions.retryAfter sono i secondi che mancano al ripristino, e l'header Retry-After riporta lo stesso numero | 429 |
INVALID_API_TOKEN | Token non trovato, malformato o comunque inutilizzabile | 200 |
I token revocati, quelli scaduti, le discrepanze tra account e i rifiuti per elenco IP consentiti vengono respinti prima che la query venga eseguita e si presentano come HTTP 401 senza corpo GraphQL. Considera un 401 su una richiesta con token come «questo token non è più valido per questa richiesta: controlla scadenza, ambiti ed elenco IP consentiti».
Limiti di frequenza
Ogni richiesta con token porta degli header:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 96
X-RateLimit-Reset: 1715692800
Il budget predefinito è di 120 richieste al minuto per token. Ogni richiesta costa 1, sia che legga sia che scriva. Il superamento restituisce HTTP 429 con un header Retry-After e extensions.code = "RATE_LIMITED"; un client ben educato attende fino al momento del ripristino.
Elenco IP consentiti
Ogni token creato in autonomia deve contenere almeno un IP o CIDR: non esistono token «da qualsiasi IP». L'IP di origine di ogni richiesta viene confrontato con l'elenco del token; una mancata corrispondenza viene rifiutata con HTTP 401 e extensions.sub_code = "ip_not_allowed".
- Sono accettati IPv4, IPv6 e intervalli CIDR. Usa
/32(IPv4) o/128(IPv6) per un singolo host. - Gli intervalli vengono validati e normalizzati al salvataggio.
- L'elenco consentito è modificabile dopo la creazione: modificarlo non cambia il segreto.
Usa un token da un punto di uscita stabile: un runner CI, un job pianificato, un NAT d'ufficio fisso o i tuoi server su un intervallo di IP noto. Un token trapelato è inutile da qualunque luogo esterno al suo elenco consentito.
Attività del token
Ogni richiesta autenticata effettuata da un token viene registrata: l'ora, il nome dell'operazione, l'IP di origine, l'esito (successo, errore, limite di frequenza, ambito negato, revocato o scaduto) e la latenza di andata e ritorno. È la traccia da controllare se un token si comporta in modo inatteso.
Versionamento e deprecazione
L'API è versionata con versioni datate YYYY-MM. Fissane una nell'URL e resterà stabile per almeno 12 mesi; le deprecazioni vengono annunciate nel canale stesso prima che scompaia qualcosa che usi. Vedi Versionamento dell'API per la politica completa.
Scoperta dello schema
Lo schema si autodescrive: usa la normale introspezione GraphQL sull'endpoint versionato per generare i tipi ed esplorare la superficie. Il GraphQL Playground interattivo è disponibile all'indirizzo …/backend/<subdomain>/playground.
Avvio rapido con curl
Gli esempi presuppongono l'host helpdesk.example.com, il sottodominio acme, la versione 2026-07 e un token in $TOKEN.
Leggere l'utente corrente (qualsiasi ambito)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ currentUser { id email firstname lastname } }"}'
Elencare i ticket recenti (tickets:read)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query ($first: Int!) {
ticketList(first: $first) {
edges { node { code subject status { name } updatedAt } }
}
}",
"variables": { "first": 10 }
}'
Pubblicare una risposta pubblica (tickets:write)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation ($input: SaveTicketInput!) {
saveTicket(input: $input) {
ticket { code }
error { code message }
}
}",
"variables": {
"input": {
"id": "TICKET-UUID-HERE",
"message": "Thanks — fixing this now.",
"messageType": "PUBLIC"
}
}
}'
Per l'uso quotidiano, la CLI hdmx racchiude tutta questa superficie dietro comandi ergonomici.