組織の API アドレスと必要なスコープを持つ認証情報を使ってください。読み取りリクエストから始めて応答を確認し、ソース管理やドキュメントのサンプルにシークレットを含めないでください。
Quire の公開 API は HTTPS 経由の REST API です。OpenAPI 3.1 ドキュメント、イベント用の署名付き webhook、AI アシスタント用 MCP サーバーを提供します。API リファレンス に全エンドポイントとイベントがあります。
アドレス
組織ごとに独自のアドレスがあり、API もその配下にあります。
https://acme.quirelms.com/api/v1/courses認証情報によって組織が決まります。ある組織のキーを別の組織のアドレスで使うと拒否されます。
OpenAPI ドキュメントは、各組織アドレスの /api/v1/openapi.json で提供されます。クライアント生成ツールは、アクセス先のバージョンを常に取得できます。
認証
API キー はスクリプトやサーバー間連携に使います。管理者が /admin/integrations/api-keys で作成してスコープを選び、キーは作成時に一度だけ表示されます。bearer token として送信します。
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 の 4 つは特権スコープで、同意画面に警告が表示されます。
リクエスト
- ページネーション: すべての一覧はカーソル方式です。
limitを渡し、次にnext_cursor(pageの値) をcursorとして、has_moreが true の間送ります (例は下記)。offset はありません。 - 更新分の取得:
updated_sinceで指定時刻以降の変更を返します。削除済みの項目を知るにはinclude_deleted=trueを併用するか、/<resource>/deletionsを読みます。 - 外部識別子: 多くのリソースは独自の
external_idを受け入れ、/<resource>/ext:{external_id}で取得または upsert できます。同期のために 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 の problem document です。
{"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 で分類してください。
| Category | Status | Retry |
|---|---|---|
validation |
422、フィールドの詳細は errors |
No |
authentication |
401 | No |
authorization |
403 | No |
not_found |
404 | No |
conflict |
409 | Sometimes |
precondition |
412 | No |
quota |
プランでは 402、サイズでは 413 | No |
rate_limit |
429、Retry-After 付き |
Yes |
upstream |
502 または 504 | Yes |
internal |
500 | Yes |
サポートへ連絡する際は request_id を伝えてください。
Webhook
/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=配信を検証する手順:
- JSON を解析する前に受信した正確なバイト列から
{webhook-id}.{webhook-timestamp}.{raw body}を組み立てます。 - サブスクリプションのシークレットで HMAC-SHA256 を計算し、base64 にします。
- 各
v1,値のwebhook-signatureと一定時間で比較します。シークレットのローテーション中は 2 つの値があり、どちらかと一致すれば有効です。 - 現在時刻から 5 分以上ずれた timestamp は拒否します。
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
Quire の MCP サーバーは組織アドレスの /mcp で、streamable HTTP を使います。MCP クライアントは /.well-known/oauth-protected-resource から OAuth サーバーを検出し、利用者は他の OAuth クライアントと同様にサインインして同意します。ツールはその利用者の権限で動作し、破壊的な操作では確認を求めます。管理者は /admin/integrations/mcp で利用可能なツールを選びます。
プランと API
API キー、OAuth クライアント、webhook、MCP サーバーはプランの API 利用権に含まれ、標準プランにはすべて含まれます。利用権のないプランではキー、クライアント、サブスクリプションの作成、REST 書き込み、MCP 接続が拒否されます。データをエクスポートできるよう REST 読み取りは引き続き利用できます。拒否は commerce.plan_entitlement コードの problem document で、カテゴリは precondition です。
拡張機能
Quire のアクティビティタイプ、ブロック、登録方法、サインイン方法、問題タイプ、レポート、テーマ、連携は、セルフホスト環境が機能を追加できる拡張レジストリに宣言されています。拡張機能はビルド時に含まれ、実行時のプラグインローダーはありません。ホスト型の組織は独自の拡張機能を追加できません。管理者は /admin/extensions で組織ごとに拡張機能を切り替えられます (管理者ガイド)。
拡張機能を書くには、packages/integration/extensions/src/sample.ts のサンプルブロックとテーマから始めます。拡張ポイントを選び、points.ts の契約を確認します。ID、バージョン、ライセンス、提供する機能、必要な機能、組織が無効化できるかを宣言します。Web アプリケーションと worker の組み立て箇所に登録し、両方で一致させます。レジストリは作成時と register 呼び出し時に各ポイントの規則を確認し、問題があればすべて列挙して登録を拒否します。その際、レジストリの状態は変わりません。拡張機能自身のテストで extensionContractProblems が空であることと、無効にすると対象機能が変わることを確認してください。