Към съдържанието

Ръководство за разработчици

REST API на Quire, OAuth, уебкуки, MCP сървър и разширения.

Преглед като Markdown

Използвайте API адреса на организацията си и идентификационен ключ с ограничени обхвати. Започнете със заявка за четене, проверете отговора и пазете тайните извън системата за контрол на версиите и примерите в документацията.

Quire има един публичен API: REST през HTTPS, описан чрез документ OpenAPI 3.1, с подписани уебкуки за събития и MCP сървър за AI асистенти. Справочникът за API изброява всички крайни точки и събития.

Адреси

Всяка организация има собствен адрес и API се намира под него:

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

Идентификационният ключ определя организацията. Ключ за една организация, използван на адреса на друга, се отхвърля.

Документът OpenAPI се предоставя на /api/v1/openapi.json на адреса на всяка организация, така че генераторите на клиенти винаги виждат версията, към която се обръщате.

Удостоверяване

API ключовете са за скриптове и интеграции сървър към сървър. Администратор създава ключ на /admin/integrations/api-keys, избира обхватите му и го вижда само веднъж. Изпратете го като bearer токен:

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

Ключовете започват с qk_live_ или qk_test_. Използвайте отделен ключ за всяка интеграция.

OAuth 2.1 е за приложения, които действат от името на влязъл потребител. Регистрирайте клиент на /admin/integrations/oauth-clients, след което използвайте потока с код за упълномощаване и PKCE (/oauth/authorize, /oauth/token) или идентификационни данни на клиента за машинен клиент. Откриването е на /.well-known/oauth-authorization-server. Обхватът ограничава какво може да прави токенът; той никога не му позволява повече, отколкото може потребителят.

Обхватите са resource:read, resource:write и resource:delete, например courses:read или enrolments:write. Четири са привилегировани и се показват с предупреждение на екрана за съгласие: audit:read, roles:write, tenants:write и users:delete.

The API keys page with one key, the person it acts as, its scopes and its status, and a form to create another.
API keys list who each key acts as and what it may reach.

Заявки

  • Странициране: всички списъци използват курсори. Подайте limit, а след това предайте next_cursor от page като cursor, докато has_more е true (вижте примера по-долу). Няма параметър за отместване.
  • Промени след дата: updated_since връща промените след зададен момент. Комбинирайте го с include_deleted=true или прочетете /<resource>/deletions, за да разберете какво е премахнато.
  • Външни идентификатори: повечето ресурси приемат ваш external_id, а /<resource>/ext:{external_id} чете по него или създава/обновява ресурс, така че синхронизацията никога не трябва да съхранява идентификаторите на Quire.
  • Идемпотентност: изпращайте заглавка Idempotency-Key при POST, PATCH и DELETE. Повторен опит със същия ключ връща първоначалния отговор, вместо да изпълни операцията отново. Груповите крайни точки го изискват.
  • Версии: основната версия е в пътя (/v1). В нея всяка несъвместима промяна е ревизия с дата, избрана чрез заглавката Quire-Version, например Quire-Version: 2026-09-20. Без заглавката се използва ревизията, актуална при издаване на ключа ви.

Страница от списък:

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

Грешки

Всяка грешка е документ проблем 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..."}

Обработвайте code, който е стабилен; detail е написан за хора, безопасен за показване и може да се променя. Ако не разпознавате код, използвайте category:

Категория Статус Повторен опит
validation 422, подробности за полетата в errors Не
authentication 401 Не
authorization 403 Не
not_found 404 Не
conflict 409 Понякога
precondition 412 Не
quota 402 за плана, 413 за размера Не
rate_limit 429, с Retry-After Да
upstream 502 или 504 Да
internal 500 Да

Посочвайте request_id, когато се свързвате с екипа за поддръжка.

Уебкуки

Абонирайте се на /admin/webhooks или чрез API на /webhook_subscriptions. Изберете събития по име (enrolment.created), по област (enrolment.*) или всички (*). Първо Quire изпраща webhook.ping; абонаментът започва, след като крайната ви точка му отговори.

Доставките следват спецификацията Standard Webhooks:

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

За да проверите доставка:

  1. Сглобете низа {webhook-id}.{webhook-timestamp}.{raw body} от точните получени байтове, преди каквото и да е парсване на JSON.
  2. Изчислете HMAC-SHA256 върху него със секретния ключ на абонамента и го кодирайте в base64.
  3. Сравнете всяка стойност v1, в webhook-signature във време с постоянно време. При ротация на секретния ключ може да има две стойности; съвпадение с която и да е е валидно.
  4. Отхвърлете времеви печат, който се различава от часовника ви с повече от пет минути.
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);
  });
}

Премахвайте дубликатите по webhook-id: една доставка може да пристигне повече от веднъж. Тялото съдържа идентификатори и кратко резюме; извличайте ресурса за текущото му състояние. Неуспешните доставки се опитват отново с нарастващи паузи до 72 часа и могат да бъдат изпратени повторно от дневника на доставките.

MCP

MCP сървърът на Quire е на /mcp на адреса на организацията, през потоков HTTP. MCP клиентът открива OAuth сървъра от /.well-known/oauth-protected-resource, а потребителят влиза и дава съгласие, както при всеки OAuth клиент. Инструментите действат от името на потребителя със същите права, а разрушителните инструменти изискват потвърждение. Администраторите избират наличните инструменти на /admin/integrations/mcp.

The AI assistants page with the server address to give an assistant and a table of the tools it can use.
AI assistants (MCP): the server address, and the tools an assistant may call.

Планове и API

API ключовете, OAuth клиентите, уебкуките и MCP сървърът са включени в правото за API на плана и всеки стандартен план го включва. При план без това право създаването на ключ, клиент или абонамент се отказва, REST записите и MCP връзките се отказват, а REST четенето остава достъпно, така че данните да могат да се експортират. Отказът е документ проблем с код commerce.plan_entitlement и категория precondition.

Разширения

Собствените типове дейности, блокове, методи за записване, методи за вход, типове въпроси, отчети, теми и интеграции на Quire се декларират чрез същия регистър на разширенията, към който може да добави self-hosted инсталация. Разширенията са компилирани в продукта: няма динамично зареждане на приставки по време на изпълнение и хоствана организация не може да добавя такива. Администраторите включват и изключват разширенията за своята организация на /admin/extensions (вижте ръководството за администратора).

За да създадете разширение, започнете от примерния блок и тема в packages/integration/extensions/src/sample.ts. Изберете точката за разширение и прочетете договора ѝ в points.ts, след това декларирайте разширението с идентификатор, версия, лиценз, предоставяните и изискваните възможности и дали организацията може да го изключи. Регистрирайте го там, където се съставят уеб приложението и работникът, така че и двата да са съгласувани. Регистърът проверява собствените правила на всяка точка при създаването му и всеки път, когато извикате register, отхвърля невалиден набор с изброени всички проблеми и оставя регистъра непроменен. Тестовете на самото разширение трябва да проверят, че extensionContractProblems е празен за него и че изключването му променя засегнатите от него възможности.

Навигация

Въведете текст за търсене…

↑↓ навигация↵ избериEsc затвори