---
title: "Guida per sviluppatori"
description: "API REST di Quire, OAuth, webhook, server MCP ed estensioni."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/it/llms.txt
> Use this file to discover all available pages before exploring further.

# Guida per sviluppatori

<span id="developer-guide"></span>

Usa l'indirizzo API della tua organizzazione e una credenziale con ambiti
specifici. Inizia con una richiesta di lettura, controlla la risposta e tieni i
segreti fuori dal controllo versione e dagli esempi della documentazione.

Quire dispone di un'API pubblica: REST su HTTPS, descritta da un documento
OpenAPI 3.1, con webhook firmati per gli eventi e un server MCP per gli
assistenti IA. La [documentazione API](https://docs.quirelms.com/api/) elenca ogni endpoint ed
evento.

## Indirizzi <!--quire:addresses-->

Ogni organizzazione ha un proprio indirizzo e l'API è disponibile al suo interno:

```
https://acme.quirelms.com/api/v1/courses
```

La credenziale determina l'organizzazione. Una chiave di un'organizzazione
usata all'indirizzo di un'altra viene rifiutata.

Il documento OpenAPI è disponibile in `/api/v1/openapi.json` all'indirizzo di
qualsiasi organizzazione, così i generatori client vedono sempre la versione a
cui stai effettuando le chiamate.

## Autenticazione <!--quire:authentication-->

Le **chiavi API** servono per script e integrazioni tra server. Un
amministratore ne crea una in `/admin/integrations/api-keys`, ne sceglie gli
ambiti e la visualizza una sola volta. Inviala come token bearer:

```
curl -H "Authorization: Bearer qk_live_..." https://acme.quirelms.com/api/v1/users?limit=50
```

Le chiavi iniziano con `qk_live_` o `qk_test_`. Assegna una chiave distinta a
ogni integrazione.

**OAuth 2.1** serve per applicazioni che agiscono per conto di una persona
connessa. Registra un client in `/admin/integrations/oauth-clients`, poi usa il
flusso del codice di autorizzazione con PKCE (`/oauth/authorize`,
`/oauth/token`) oppure le credenziali client per un client macchina. La
discovery è disponibile in `/.well-known/oauth-authorization-server`. Un ambito
restringe ciò che un token può fare; non gli consente mai di fare più di quanto
possa fare la persona.

Gli ambiti sono `resource:read`, `resource:write` e `resource:delete`, per
esempio `courses:read` o `enrolments:write`. Quattro sono privilegiati e
vengono segnalati nella schermata di consenso: `audit:read`, `roles:write`,
`tenants:write` e `users:delete`.

<figure class="quire-shot" lang="en" dir="ltr"><img src="/screenshots/admin-api-keys.webp" alt="The API keys page with one key, the person it acts as, its scopes and its status, and a form to create another." width="944" height="700" loading="lazy" decoding="async"><figcaption>API keys list who each key acts as and what it may reach.</figcaption></figure>

## Richieste <!--quire:requests-->

- **Paginazione**: ogni elenco usa cursori. Passa `limit`, poi il `next_cursor`
  di `page` come `cursor` finché `has_more` è true (vedi esempio
  sotto). Non esiste l'offset.
- **Modifiche successive**: `updated_since` restituisce ciò che è cambiato dopo
  un dato orario. Abbinalo a `include_deleted=true` oppure leggi
  `/<resource>/deletions` per sapere cosa è stato rimosso.
- **Identificativi esterni**: la maggior parte delle risorse accetta il tuo
  `external_id`, e `/<resource>/ext:{external_id}` permette di leggere o
  aggiornare per identificativo esterno, così una sincronizzazione non deve
  conservare gli identificativi di Quire.
- **Idempotenza**: invia l'intestazione `Idempotency-Key` con `POST`, `PATCH`
  e `DELETE`. Un nuovo tentativo con la stessa chiave restituisce la prima
  risposta invece di ripetere l'operazione. Gli endpoint in blocco la
  richiedono.
- **Versioni**: il numero di versione principale è nel percorso (`/v1`). Al
  suo interno, ogni modifica incompatibile è una revisione datata, selezionata
  con l'intestazione `Quire-Version`, per esempio `Quire-Version: 2026-09-20`.
  Senza intestazione ricevi la revisione corrente al momento del rilascio della
  credenziale.

Una pagina di un elenco:

```
{"data": [...], "page": {"next_cursor": "eyJ2Ijox...", "has_more": true, "limit": 100}}
```

## Errori <!--quire:errors-->

Ogni errore è un documento di problema RFC 9457:

```
{"type": "https://quire.com/errors/enrolment.seat_limit_reached",
 "title": "Seat limit reached", "status": 409,
 "code": "enrolment.seat_limit_reached", "category": "conflict",
 "detail": "The course has no seats left, so this enrolment was not created. ...",
 "request_id": "01JB7XQK4Z..."}
```

Gestisci gli errori in base a `code`, che è stabile; `detail` è scritto per le
persone, è sicuro da mostrare e può cambiare. Se non riconosci un codice, usa
`category`:

| Categoria | Stato | Nuovo tentativo |
| --- | --- | --- |
| `validation` | 422, con dettagli dei campi in `errors` | No |
| `authentication` | 401 | No |
| `authorization` | 403 | No |
| `not_found` | 404 | No |
| `conflict` | 409 | A volte |
| `precondition` | 412 | No |
| `quota` | 402 per il piano, 413 per le dimensioni | No |
| `rate_limit` | 429, con `Retry-After` | Sì |
| `upstream` | 502 o 504 | Sì |
| `internal` | 500 | Sì |

Quando contatti l'assistenza, comunica `request_id`.

## Webhook <!--quire:webhooks-->

Sottoscrivi gli eventi in `/admin/webhooks` oppure tramite l'API in
`/webhook_subscriptions`. Scegli gli eventi per nome (`enrolment.created`),
per area (`enrolment.*`) o tutti (`*`). Quire invia prima un `webhook.ping`; la
sottoscrizione inizia quando il tuo endpoint risponde.

Le consegne seguono la specifica Standard Webhooks:

```
POST /hooks/quire
webhook-id: 01JB7XQK4Z8FQ2M3N4P5R6S7T8
webhook-timestamp: 1790000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=
```

Per verificare una consegna:

1. Crea la stringa `{webhook-id}.{webhook-timestamp}.{raw body}` dai byte
   esatti ricevuti, prima di analizzare JSON.
2. Calcola HMAC-SHA256 usando il segreto della sottoscrizione e codifica il
   risultato in base64.
3. Confrontalo in tempo costante con ogni valore `v1,` di
   `webhook-signature`. Durante la rotazione del segreto possono essercene due:
   basta che corrisponda uno.
4. Rifiuta un timestamp che differisce dal tuo orologio di più di cinque minuti.

```
import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(secret, id, timestamp, rawBody, header) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  const expected = createHmac('sha256', Buffer.from(secret.replace(/^whsec_/, ''), 'base64'))
    .update(`${id}.${timestamp}.${rawBody}`).digest();
  return header.split(' ').some((part) => {
    const [version, value] = part.split(',');
    const given = Buffer.from(value ?? '', 'base64');
    return version === 'v1' && given.length === expected.length && timingSafeEqual(given, expected);
  });
}
```

Evita duplicati usando `webhook-id`: la stessa consegna può arrivare più volte.
Il corpo contiene identificativi e un breve riepilogo; recupera la risorsa per
conoscerne lo stato corrente. Le consegne non riuscite vengono ritentate con
intervalli crescenti per un massimo di 72 ore e possono essere riprodotte dal
log di consegna.

## MCP <!--quire:mcp-->

Il server MCP di Quire è disponibile in `/mcp` all'indirizzo
dell'organizzazione tramite HTTP trasmissibile. Un client MCP individua il
server OAuth da `/.well-known/oauth-protected-resource`, quindi la persona
accede e concede il consenso come con qualsiasi client OAuth. Gli strumenti
agiscono con i permessi di quella persona; quelli distruttivi chiedono una
conferma. Gli amministratori scelgono gli strumenti disponibili in
`/admin/integrations/mcp`.

<figure class="quire-shot" lang="en" dir="ltr"><img src="/screenshots/admin-mcp.webp" alt="The AI assistants page with the server address to give an assistant and a table of the tools it can use." width="944" height="700" loading="lazy" decoding="async"><figcaption>AI assistants (MCP): the server address, and the tools an assistant may call.</figcaption></figure>

## Piani e API <!--quire:plans-and-the-api-->

Le chiavi API, i client OAuth, i webhook e il server MCP fanno parte del diritto
all'API incluso in ogni piano standard. Se il piano non lo include, la
creazione di chiavi, client o sottoscrizioni viene rifiutata, le scritture REST
e le connessioni MCP vengono rifiutate, mentre le letture REST continuano a
funzionare per consentire l'esportazione dei dati. Il rifiuto è un documento di
problema con codice `commerce.plan_entitlement`, nella categoria
`precondition`.

## Estensioni <!--quire:extensions-->

Tipi di attività, blocchi, metodi di iscrizione e di accesso, tipi di domande,
rapporti, temi e integrazioni di Quire sono dichiarati tramite lo stesso
registro delle estensioni che può essere ampliato nelle installazioni
autogestite. Le estensioni sono incluse in fase di compilazione: non esiste un
caricatore di plugin durante l'esecuzione e le organizzazioni che usano il
servizio ospitato non possono aggiungerne. Gli amministratori attivano o
disattivano ogni estensione per la propria organizzazione in
`/admin/extensions` (vedi la [guida per amministratori](/it/admin/extensions/)).

Per crearne una, parti dall'esempio di blocco e tema in
`packages/integration/extensions/src/sample.ts`. Scegli il punto di estensione
e leggine il contratto in `points.ts`; poi dichiara l'estensione con
identificativo, versione, licenza, requisiti, elementi forniti e indicazione
che stabilisce se un'organizzazione può disattivarla. Registrala nel punto in
cui vengono composti l'applicazione web e il worker, così entrambi concordano.
Il registro controlla le regole specifiche del punto durante la creazione e a
ogni chiamata a `register`; rifiuta un insieme non valido indicando ogni
problema e lascia invariato il registro. I test dell'estensione dovrebbero
verificare che `extensionContractProblems` non segnali problemi per essa e che
disattivarla modifichi ciò che influenza.

Source: https://docs.quirelms.com/it/developer/index.mdx
