---
title: "Kehittäjän opas"
description: "Quiren REST API, OAuth, webhookit, MCP-palvelin ja laajennukset."
image: "https://docs.quirelms.com/og.png"
---

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

# Kehittäjän opas

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

Käytä organisaatiosi API-osoitetta ja rajattua tunnistetietoa. Aloita lukupyynnöllä, tarkista vastaus ja säilytä salaisuudet versionhallinnan ja dokumentaatioesimerkkien ulkopuolella.

Quiressa on yksi julkinen API: HTTPS-yhteydellä käytettävä REST-rajapinta, joka on kuvattu OpenAPI 3.1 -dokumentissa, tapahtumien allekirjoitetut webhookit ja tekoälyavustajien MCP-palvelin. [API-viite](https://docs.quirelms.com/api/) luettelee kaikki päätepisteet ja tapahtumat.

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

Jokaisella organisaatiolla on oma osoite, jonka alla sen API sijaitsee:

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

Tunnistetieto määrittää organisaation. Yhden organisaation avain hylätään toisen organisaation osoitteessa.

OpenAPI-dokumentti tarjoillaan minkä tahansa organisaation osoitteessa `/api/v1/openapi.json`, joten asiakasohjelmien generaattorit näkevät aina käyttämäsi version.

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

**API-avaimet** sopivat komentojonoille ja palvelinten välisille integraatioille. Ylläpitäjä luo avaimen osoitteessa `/admin/integrations/api-keys`, valitsee sen käyttöoikeudet ja näkee sen vain kerran. Lähetä avain bearer-tokenina:

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

Avaimen alku on `qk_live_` tai `qk_test_`. Luo jokaiselle integraatiolle oma avain.

**OAuth 2.1** sopii sovelluksille, jotka toimivat kirjautuneen henkilön nimissä. Rekisteröi asiakas osoitteessa `/admin/integrations/oauth-clients` ja käytä sen jälkeen PKCE-suojattua valtuutuskoodivirtaa (`/oauth/authorize`, `/oauth/token`) tai konetilin client credentials -menetelmää. Palvelun määritys löytyy osoitteesta `/.well-known/oauth-authorization-server`. Käyttöoikeus rajaa tokenin toimintoja; se ei koskaan anna henkilölle kuuluvia oikeuksia laajempia oikeuksia.

Käyttöoikeudet ovat muotoa `resource:read`, `resource:write` ja `resource:delete`, esimerkiksi `courses:read` tai `enrolments:write`. Neljä etuoikeutettua oikeutta näytetään suostumusnäkymässä varoituksen kanssa: `audit:read`, `roles:write`, `tenants:write` ja `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>

## Pyynnöt <!--quire:requests-->

- **Sivutus**: kaikki luettelot käyttävät osoitinkursoria. Anna `limit` ja välitä sitten `next_cursor`-arvo `page`-objektista seuraavan pyynnön parametrina `cursor`, kun `has_more` on tosi (esimerkki alla). Offset-sivutusta ei ole.
- **Muutokset tietyn ajan jälkeen**: `updated_since` palauttaa sen jälkeen muuttuneet tiedot. Käytä yhdessä sen kanssa asetusta `include_deleted=true` tai hae osoitteesta `/<resource>/deletions`, niin näet myös poistetut kohteet.
- **Ulkoiset tunnisteet**: useimmat resurssit hyväksyvät oman `external_id`-arvon. `/<resource>/ext:{external_id}` hakee tai päivittää tiedon sen perusteella, joten synkronointi ei tarvitse Quiren tunnisteiden tallentamista.
- **Idempotenssi**: lähetä `Idempotency-Key`-otsake pyynnöissä `POST`, `PATCH` ja `DELETE`. Samalla avaimella tehty uudelleenyritys palauttaa ensimmäisen vastauksen tekemättä toimintoa uudelleen. Joukkopäätepisteet vaativat avaimen.
- **Versiot**: pääversio on polussa (`/v1`). Sen sisällä kukin rikkova muutos on päivämäärällä merkitty versio, joka valitaan `Quire-Version`-otsakkeella, esimerkiksi `Quire-Version: 2026-09-20`. Ilman otsaketta käytetään tunnistetietosi myöntämisen aikaan voimassa ollutta versiota.

Esimerkki luettelon sivusta:

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

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

Kaikki virheet palautetaan RFC 9457 -ongelmadokumentteina:

```
{"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..."}
```

Käsittele pysyvän tunnisteen `code` perusteella. Ihmisille kirjoitettu `detail` on turvallista näyttää käyttäjille, mutta sen sanamuoto voi muuttua. Jos koodi on tuntematon, luokittele virhe `category`-arvon perusteella:

| Luokka | Tila | Yritä uudelleen |
| --- | --- | --- |
| `validation` | 422, kenttäkohtaiset tiedot `errors`-arvossa | Ei |
| `authentication` | 401 | Ei |
| `authorization` | 403 | Ei |
| `not_found` | 404 | Ei |
| `conflict` | 409 | Joskus |
| `precondition` | 412 | Ei |
| `quota` | 402 paketin vuoksi, 413 koon vuoksi | Ei |
| `rate_limit` | 429 ja `Retry-After` | Kyllä |
| `upstream` | 502 tai 504 | Kyllä |
| `internal` | 500 | Kyllä |

Mainitse tukipyynnössä `request_id`.

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

Tilaa webhook osoitteessa `/admin/webhooks` tai API:n kautta osoitteessa `/webhook_subscriptions`. Valitse tapahtumat nimellä (`enrolment.created`), aihealueittain (`enrolment.*`) tai kaikki (`*`). Quire lähettää ensin `webhook.ping`-tapahtuman. Tilaus alkaa, kun päätepisteesi vastaa siihen.

Toimitukset noudattavat Standard Webhooks -määritystä:

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

Tarkista toimitus näin:

1. Muodosta vastaanotetuista tarkoista tavuista ennen JSON-jäsennystä merkkijono `{webhook-id}.{webhook-timestamp}.{raw body}`.
2. Laske merkkijonosta HMAC-SHA256 tilauksen salaisuudella ja koodaa tulos base64-muotoon.
3. Vertaa sitä vakioajassa `v1,`-arvoihin, jotka ovat `webhook-signature`-otsakkeessa. Salaisuutta vaihdettaessa arvoja voi olla kaksi; kumpi tahansa kelpaa.
4. Hylkää aikaleima, joka poikkeaa kellostasi yli viidellä minuutilla.

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

Poista kaksoistoimitukset `webhook-id`-tunnisteen perusteella, sillä toimitus voi tulla useammin kuin kerran. Runko sisältää tunnisteet ja lyhyen yhteenvedon. Hae resurssi, kun tarvitset sen ajantasaisen tilan. Epäonnistunutta toimitusta yritetään uudelleen kasvavilla viiveillä enintään 72 tuntia, ja se voidaan toistaa toimituslokista.

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

Quiren MCP-palvelin sijaitsee organisaation osoitteessa `/mcp`, ja sen kanssa viestitään streamattavalla HTTP-yhteydellä. MCP-asiakas löytää OAuth-palvelimen osoitteesta `/.well-known/oauth-protected-resource`. Käyttäjä kirjautuu sisään ja antaa suostumuksensa kuten mille tahansa OAuth-asiakkaalle. Työkalut toimivat käyttäjän oikeuksilla, ja tuhoavat toiminnot pyytävät vahvistusta. Ylläpitäjät valitsevat käytettävissä olevat työkalut osoitteessa `/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>

## Palvelupaketit ja API <!--quire:plans-and-the-api-->

API-avaimet, OAuth-asiakkaat, webhookit ja MCP-palvelin kuuluvat paketin API-oikeuteen, joka sisältyy jokaiseen tavalliseen palvelupakettiin. Jos paketti ei sisällä sitä, avaimen, asiakkaan tai tilauksen luonti estetään, REST-kirjoituspyynnöt ja MCP-yhteydet estetään ja REST-lukupyynnöt toimivat edelleen tietojen viemistä varten. Estosta palautetaan ongelmadokumentti, jonka koodi on `commerce.plan_entitlement` ja luokka `precondition`.

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

Quiren omat toimintotyypit, lohkot, ilmoittautumistavat, kirjautumistavat, kysymystyypit, raportit, teemat ja integraatiot määritellään samassa laajennusrekisterissä, johon itse ylläpidetyssä asennuksessa voi lisätä laajennuksia. Laajennukset käännetään osaksi sovellusta. Käyttöaikaista lisäosien lataajaa ei ole, eikä isännöity organisaatio voi lisätä laajennuksia. Ylläpitäjät ottavat laajennukset käyttöön tai poistavat ne käytöstä osoitteessa `/admin/extensions` (katso [ylläpitäjän opas](/fi/admin/extensions/)).

Aloita laajennuksen kirjoittaminen tiedoston `packages/integration/extensions/src/sample.ts` esimerkkilohkosta ja teemasta. Valitse laajennuspiste ja lue sen sopimus tiedostosta `points.ts`. Määritä sitten laajennukselle tunniste, versio, lisenssi, sen tarjoamat ja tarvitsemat asiat sekä tieto siitä, saako organisaatio poistaa sen käytöstä. Rekisteröi laajennus kohtaan, jossa verkkosovellus ja työntekijäprosessi kootaan, jotta ne ovat samaa mieltä. Rekisteri tarkistaa kunkin laajennuspisteen säännöt luonnin yhteydessä ja jokaisella `register`-kutsulla. Se hylkää virheellisen kokonaisuuden ilmoittaen kaikki ongelmat ja jättää rekisterin ennalleen. Laajennuksen omissa testeissä tulee varmistaa, että `extensionContractProblems` ei ilmoita ongelmia ja että käytöstä poistaminen muuttaa sen vaikutuksia.

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