---
title: "Guida per sviluppatori"
description: "L'API REST di Quire, OAuth, webhooks, u servitore MCP è l'estensioni."
image: "https://docs.quirelms.com/og.png"
---

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

# Guida per sviluppatori

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

Aduprate l'indirizzu API di a vostra urganizazione è una credenziale cù permessi limitati. Cuminciate cù una dumanda di lettura, verificate a risposta, è tenite i sicreti fora di u cuntrollu di versione è di l'esempii di ducumentazione.

Quire hà una sola API publica: REST sopra HTTPS, discritta da un
ducumentu OpenAPI 3.1, cù webhooks firmati per l'avvenimenti è un servitore MCP per
l'assistenti IA. A [riferenza API](https://docs.quirelms.com/api/) elenca tutti l'endpoint è l'avvenimenti.

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

Ogni urganizazione hà u so indirizzu, è l'API hè dispunibule sottu à quellu:

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

A credenziale determina l'urganizazione. Una chjave d'una urganizazione aduprata à
l'indirizzu d'un'altra hè ricusata.

U ducumentu OpenAPI hè servutu in `/api/v1/openapi.json` à l'indirizzu di qualsiasi
urganizazione, cusì i generatori di clienti vedenu sempre a versione chì state
chjamendu.

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

**E chjave API** sò per i script è l'integrazioni trà servitori. Un
amministratore ne crea una in `/admin/integrations/api-keys`, ne sceglie i
permissi, è a vede una sola volta. Mandate la cum'è gettone bearer:

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

E chjave principianu cù `qk_live_` o `qk_test_`. Date à ogni integrazione a so propria chjave.

**OAuth 2.1** hè per l'applicazioni chì agiscenu cum'è una persona cunnessa. Registrate
un cliente in `/admin/integrations/oauth-clients`, dopu aduprate u flussu di codice
d'auturizazione cù PKCE (`/oauth/authorize`, `/oauth/token`), o e credenziali di cliente
per un cliente macchina. A scuperta hè in
`/.well-known/oauth-authorization-server`. Un permessu restringe ciò chì un gettone pò
fà; ùn li permette mai di fà di più chè a persona.

I permessi sò `resource:read`, `resource:write` è `resource:delete`, per
esempiu `courses:read` o `enrolments:write`. Quattru sò privilegiati è mustrati
cù un avvirtimentu nantu à u schermu di cunsensu: `audit:read`, `roles:write`,
`tenants:write` è `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>

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

- **Paginazione**: ogni lista hè paginata cù cursori. Passate `limit`, dopu u
  `next_cursor` di `page` cum'è `cursor` mentre `has_more` hè veru (esempiu
  sottu). Ùn ci hè micca offset.
- **Cambiamenti dapoi**: `updated_since` restituisce ciò chì hè cambiatu dopu à un'ora.
  Assuciate lu à `include_deleted=true`, o leghjite `/<resource>/deletions`, per
  sapè ciò chì hè statu sguassatu.
- **Identificatori esterni**: a maiò parte di e risorse accettanu u vostru `external_id`,
  è `/<resource>/ext:{external_id}` leghje o aghjurna per mezu di quellu, cusì una
  sincronizazione ùn hà mai bisognu di cunservà l'identificatori di Quire.
- **Idempotenza**: mandate un'intestazione `Idempotency-Key` cù `POST`, `PATCH` è
  `DELETE`. Una riprova cù a stessa chjave restituisce a prima risposta invece di
  ripete l'operazione. L'endpoint in lottu l'esigenu.
- **Versioni**: a versione maiò hè in u percorsu (`/v1`). Dentru ella, ogni
  cambiamentu chì rompe a cumpatibilità hè una revisione datata, scelta cù l'intestazione
  `Quire-Version`, per esempiu `Quire-Version: 2026-09-20`. Senza l'intestazione ricevete
  a revisione attuale quandu a vostra credenziale hè stata emessa.

Una pagina d'una lista:

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

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

Ogni errore hè un ducumentu di prublema 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..."}
```

Determinate a gestione secondu `code`, chì hè stabile; `detail` hè scrittu per e persone, si pò
mustà à l'utilizatori, è pò cambià. S'è ùn ricunniscite micca un codice, raggruppate secondu
`category`:

| Categoria | Statu | Riprova |
| --- | --- | --- |
| `validation` | 422, cù u dettagliu di u campu in `errors` | Innò |
| `authentication` | 401 | Innò |
| `authorization` | 403 | Innò |
| `not_found` | 404 | Innò |
| `conflict` | 409 | Qualchì volta |
| `precondition` | 412 | Innò |
| `quota` | 402 per u pianu, 413 per a dimensione | Innò |
| `rate_limit` | 429, cù `Retry-After` | Iè |
| `upstream` | 502 o 504 | Iè |
| `internal` | 500 | Iè |

Citate `request_id` quandu cuntattate u supportu.

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

Abbonate vi in `/admin/webhooks`, o per mezu di l'API in
`/webhook_subscriptions`. Sceglite l'avvenimenti per nome (`enrolment.created`),
per area (`enrolment.*`) o tutti (`*`). Quire manda prima un `webhook.ping`; l'
abbonamentu principia quandu u vostru endpoint risponde.

E cunsegne seguitanu a specificazione Standard Webhooks:

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

Per verificà una cunsegna:

1. Custruite a stringa `{webhook-id}.{webhook-timestamp}.{raw body}` da i
   byte esatti ricevuti, prima di analizà ogni JSON.
2. Calculate HMAC-SHA256 annantu à ella cù u sicretu di l'abbonamentu, è cunvertite u risultatu in base64.
3. Cunfruntate in tempu custante ogni valore `v1,` in `webhook-signature`.
   Ci ne ponu esse dui durante una rotazione di sicretu; una currispundenza basta.
4. Ricusate un timestamp chì hè à più di cinque minuti da u vostru clock.

```
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);
  });
}
```

Eliminate i duplicati cù `webhook-id`: una cunsegna pò ghjunghje più d'una volta. U corpu
porta identificatori è un riassuntu cortu; scaricate a risorsa per ottene u so statu attuale.
E cunsegne fallite sò ritentate cù attese crescenti finu à 72 ore, è
ponu esse rimandate da u registru di cunsegne.

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

U servitore MCP di Quire hè in `/mcp` à l'indirizzu di l'urganizazione, via
HTTP streamable. Un cliente MCP scopre u servitore OAuth per mezu di
`/.well-known/oauth-protected-resource`, è a persona si cunnette è
accunsente cum'è cù qualsiasi cliente OAuth. I strumenti agiscenu cù i permessi di
quella persona, è l'azzioni distruttive dumandanu cunferma. L'amministratori
sceglienu i strumenti dispunibuli 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 è API <!--quire:plans-and-the-api-->

E chjave API, i clienti OAuth, i webhooks è u servitore MCP appartenenu à u dirittu API
di u pianu, è ogni pianu standard l'include. In un pianu senza quellu dirittu, a creazione
d'una chjave, d'un cliente o d'un abbonamentu hè ricusata, e scritture REST è e
cunnessioni MCP sò ricusate, è e letture REST cuntinueghjanu à funziunà per chì i dati ferminu esportabili. U rifiutu hè un ducumentu di prublema cù u
codice `commerce.plan_entitlement`, in a categuria `precondition`.

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

I tipi d'attività, i blocchi, i metudi d'iscrizzione, i metudi di cunnessione,
i tipi di dumanda, i rapporti, i temi è l'integrazioni propii di Quire sò dichjarati attraversu u listessu registru
d'estensioni chì una installazione autugestionata pò allargà. L'estensioni sò cumpilate:
ùn ci hè micca un caricatore di plugins in esecuzione, è un'urganizazione ospitata ùn ne pò aghjunghje.
L'amministratori attivanu o disattivanu ogni estensione per a so urganizazione in
`/admin/extensions` (vede a [guida amministrativa](/co/admin/extensions/)).

Per scrive ne una, partite da u bloccu è u tema d'esempiu in
`packages/integration/extensions/src/sample.ts`. Sceglite u puntu d'estensione è
leghjite u so cuntrattu in `points.ts`, dopu dichjarate l'estensione cù un ID, una versione,
una licenza, ciò ch'ella furnisce è ciò ch'ella richiede, è s'è un'urganizazione a pò disattivà.
Registrate la induve sò cumposti l'applicazione web è u worker, affinch'è tramindui
sianu d'accordu. U registru verifica e regule proprie di ogni puntu à a so custruzzione è ogni volta chì
chjamate `register`, ricusa un inseme chì ùn seria micca validu indicendu ogni prublema,
è lascia u registru intattu. I testi di l'estensione devenu verificà
chì `extensionContractProblems` sia viotu per ella è chì disattivà la cambi
ciò ch'ella influenza.

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