---
title: "Vodič za razvojne inženjere"
description: "Quireov REST API, OAuth, webhookovi, MCP poslužitelj i proširenja."
image: "https://docs.quirelms.com/og.png"
---

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

# Vodič za razvojne inženjere

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

Upotrijebite API adresu svoje organizacije i vjerodajnicu ograničenog opsega. Započnite
zahtjevom za čitanje, provjerite odgovor i držite tajne izvan kontrole izvornog koda i
primjera u dokumentaciji.

Quire ima jedan javni API: REST preko HTTPS-a, opisan dokumentom OpenAPI 3.1, potpisane
webhookove za događaje i MCP poslužitelj za pomoćnike umjetne inteligencije.
[Referenca API-ja](https://docs.quirelms.com/api/) navodi svaku krajnju točku i događaj.

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

Svaka organizacija ima vlastitu adresu, a API se nalazi pod njom:

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

Vjerodajnica određuje organizaciju. Ključ za jednu organizaciju neće biti prihvaćen
na adresi druge.

Dokument OpenAPI poslužuje se na `/api/v1/openapi.json` na adresi bilo koje organizacije,
tako da generatori klijenata uvijek vide verziju koju pozivate.

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

**API ključevi** namijenjeni su skriptama i integracijama poslužitelj-na-poslužitelj.
Administrator izrađuje ključ na `/admin/integrations/api-keys`, bira njegove opsege
i vidi ga samo jednom. Pošaljite ga kao bearer token:

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

Ključevi počinju s `qk_live_` ili `qk_test_`. Svakoj integraciji dodijelite zaseban ključ.

**OAuth 2.1** namijenjen je aplikacijama koje djeluju u ime prijavljene osobe. Registrirajte
klijenta na `/admin/integrations/oauth-clients`, a zatim upotrijebite tijek koda za
autorizaciju s PKCE-om (`/oauth/authorize`, `/oauth/token`) ili vjerodajnice klijenta
za strojni klijent. Otkrivanje je na `/.well-known/oauth-authorization-server`.
Opseg ograničava mogućnosti tokena; nikad mu ne dopušta više nego što smije sama osoba.

Opsezi su `resource:read`, `resource:write` i `resource:delete`, primjerice
`courses:read` ili `enrolments:write`. Četiri imaju povišene ovlasti i prikazuju se
uz upozorenje na zaslonu pristanka: `audit:read`, `roles:write`, `tenants:write` i
`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>

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

- **Paginacija**: svi se popisi paginiraju pokazivačem. Pošaljite `limit`, a zatim
  `next_cursor` iz `page` kao `cursor` dok je `has_more` true (primjer je u nastavku).
  Offset se ne upotrebljava.
- **Promjene od**: `updated_since` vraća promjene nakon vremena. Kombinirajte ga s
  `include_deleted=true` ili pročitajte `/<resource>/deletions` kako biste saznali
  što je uklonjeno.
- **Vanjski identifikatori**: većina resursa prihvaća vaš `external_id`, a
  `/<resource>/ext:{external_id}` dohvaća ili umeće zapis prema njemu, pa sinkronizacija
  ne mora pohranjivati Quireove identifikatore.
- **Idempotentnost**: šaljite zaglavlje `Idempotency-Key` uz `POST`, `PATCH` i `DELETE`.
  Ponovljeni zahtjev s istim ključem vraća prvi odgovor umjesto da dvaput obavi posao.
  Skupne krajnje točke zahtijevaju taj ključ.
- **Verzije**: glavna verzija nalazi se u putanji (`/v1`). Unutar nje svaka promjena
  koja narušava kompatibilnost zasebna je datirana revizija koju određuje zaglavlje
  `Quire-Version`, primjerice `Quire-Version: 2026-09-20`. Bez zaglavlja dobivate
  reviziju koja je bila aktualna kad je izdana vaša vjerodajnica.

Stranica popisa:

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

## Pogreške <!--quire:errors-->

Svaka je pogreška problem-dokument prema RFC-u 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..."}
```

Granu račvajte prema `code`, koji je stabilan; `detail` je namijenjen ljudima, sigurno
ga je prikazati i može se promijeniti. Ako ne prepoznajete kôd, razvrstajte prema
`category`:

| Kategorija | Status | Ponovni pokušaj |
| --- | --- | --- |
| `validation` | 422, s pojedinostima polja u `errors` | Ne |
| `authentication` | 401 | Ne |
| `authorization` | 403 | Ne |
| `not_found` | 404 | Ne |
| `conflict` | 409 | Ponekad |
| `precondition` | 412 | Ne |
| `quota` | 402 za plan, 413 za veličinu | Ne |
| `rate_limit` | 429, sa zaglavljem `Retry-After` | Da |
| `upstream` | 502 ili 504 | Da |
| `internal` | 500 | Da |

Kada kontaktirate podršku, navedite `request_id`.

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

Pretplatite se na `/admin/webhooks` ili putem API-ja na `/webhook_subscriptions`.
Odaberite događaje po nazivu (`enrolment.created`), području (`enrolment.*`) ili sve
(`*`). Quire najprije šalje `webhook.ping`; pretplata počinje kada vaša krajnja točka
odgovori na njega.

Isporuke slijede specifikaciju Standard Webhooks:

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

Za provjeru isporuke:

1. Sastavite niz `{webhook-id}.{webhook-timestamp}.{raw body}` iz točno primljenih
   bajtova prije bilo kakve obrade JSON-a.
2. Izračunajte HMAC-SHA256 nad njim pomoću tajne pretplate i kodirajte ga u base64.
3. U konstantnom vremenu usporedite sa svakom vrijednošću `v1,` u
   `webhook-signature`. Tijekom rotacije tajne mogu postojati dvije; vrijedi bilo koja
   podudarna vrijednost.
4. Odbacite vremensku oznaku koja se od vašeg sata razlikuje više od pet minuta.

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

Spriječite duplikate prema `webhook-id`: isporuka može stići više puta. Tijelo nosi
identifikatore i kratak sažetak; dohvatite resurs da biste vidjeli njegovo trenutačno
stanje. Neuspjele se isporuke ponovno pokušavaju uz postupno povećanje razmaka do
72 sata, a mogu se i ponovno pokrenuti iz zapisnika isporuka.

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

Quireov MCP poslužitelj nalazi se na `/mcp` na adresi organizacije i koristi HTTP
koji podržava streaming. MCP klijent otkriva OAuth poslužitelj preko
`/.well-known/oauth-protected-resource`, a osoba se prijavljuje i daje pristanak kao
i svaki drugi OAuth klijent. Alati djeluju s njezinim dozvolama, a destruktivni alati
traže potvrdu. Administratori biraju dostupne alate na `/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>

## Planovi i API <!--quire:plans-and-the-api-->

API ključevi, OAuth klijenti, webhookovi i MCP poslužitelj pripadaju API pogodnostima
plana, a obuhvaćeni su svakim standardnim planom. U planu bez te pogodnosti odbija se
stvaranje ključa, klijenta ili pretplate, kao i REST upisi i MCP veze; REST čitanje
ostaje dostupno kako bi se podaci mogli izvesti. Odbijanje je problem-dokument s
kôdom `commerce.plan_entitlement` i kategorijom `precondition`.

## Proširenja <!--quire:extensions-->

Quireove vrste aktivnosti, blokovi, načini upisa i prijave, vrste pitanja, izvješća,
teme i integracije deklariraju se putem istog registra proširenja kojem instalacija
koju sami hostate može dodavati proširenja. Proširenja su ugrađena pri kompilaciji:
nema učitavača dodataka tijekom rada, a organizacija na hostanoj usluzi ne može dodati
proširenje. Administratori uključuju ili isključuju pojedina proširenja za organizaciju
na `/admin/extensions` (pogledajte [vodič za administratore](/hr/admin/extensions/)).

Za izradu proširenja počnite s oglednim blokom i temom u
`packages/integration/extensions/src/sample.ts`. Odaberite točku proširenja i pročitajte
njezin ugovor u `points.ts`, zatim deklarirajte proširenje s ID-jem, verzijom, licencom,
onim što nudi i zahtijeva te podatkom može li ga organizacija isključiti. Registrirajte
ga ondje gdje se sastavljaju web-aplikacija i worker kako bi se slagali. Registar
provjerava pravila svake točke pri izradi i pri svakom pozivu `register`, odbija skup
koji nije valjan i navodi sve probleme, a registar pritom ostaje nepromijenjen. Testovi
proširenja trebali bi potvrditi da je `extensionContractProblems` za njega prazan i da
isključivanje mijenja ono na što utječe.

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