---
title: "開発者ガイド"
description: "Quire REST API、OAuth、webhook、MCP サーバー、拡張機能について説明します。"
image: "https://docs.quirelms.com/og.png"
---

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

# 開発者ガイド

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

組織の API アドレスと必要なスコープを持つ認証情報を使ってください。読み取りリクエストから始めて応答を確認し、ソース管理やドキュメントのサンプルにシークレットを含めないでください。

Quire の公開 API は HTTPS 経由の REST API です。OpenAPI 3.1 ドキュメント、イベント用の署名付き webhook、AI アシスタント用 MCP サーバーを提供します。[API リファレンス](https://docs.quirelms.com/api/) に全エンドポイントとイベントがあります。

## アドレス <!--quire:addresses-->

組織ごとに独自のアドレスがあり、API もその配下にあります。

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

認証情報によって組織が決まります。ある組織のキーを別の組織のアドレスで使うと拒否されます。

OpenAPI ドキュメントは、各組織アドレスの `/api/v1/openapi.json` で提供されます。クライアント生成ツールは、アクセス先のバージョンを常に取得できます。

## 認証 <!--quire:authentication-->

**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 つは特権スコープで、同意画面に警告が表示されます。

<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>

## リクエスト <!--quire:requests-->

- **ページネーション**: すべての一覧はカーソル方式です。`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}}
```

## エラー <!--quire:errors-->

すべてのエラーは 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 <!--quire:webhooks-->

`/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. JSON を解析する前に受信した正確なバイト列から `{webhook-id}.{webhook-timestamp}.{raw body}` を組み立てます。
2. サブスクリプションのシークレットで HMAC-SHA256 を計算し、base64 にします。
3. 各 `v1,` 値の `webhook-signature`と一定時間で比較します。シークレットのローテーション中は 2 つの値があり、どちらかと一致すれば有効です。
4. 現在時刻から 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-->

Quire の MCP サーバーは組織アドレスの `/mcp` で、streamable HTTP を使います。MCP クライアントは `/.well-known/oauth-protected-resource` から OAuth サーバーを検出し、利用者は他の OAuth クライアントと同様にサインインして同意します。ツールはその利用者の権限で動作し、破壊的な操作では確認を求めます。管理者は `/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>

## プランと API <!--quire:plans-and-the-api-->

API キー、OAuth クライアント、webhook、MCP サーバーはプランの API 利用権に含まれ、標準プランにはすべて含まれます。利用権のないプランではキー、クライアント、サブスクリプションの作成、REST 書き込み、MCP 接続が拒否されます。データをエクスポートできるよう REST 読み取りは引き続き利用できます。拒否は `commerce.plan_entitlement` コードの problem document で、カテゴリは `precondition` です。

## 拡張機能 <!--quire:extensions-->

Quire のアクティビティタイプ、ブロック、登録方法、サインイン方法、問題タイプ、レポート、テーマ、連携は、セルフホスト環境が機能を追加できる拡張レジストリに宣言されています。拡張機能はビルド時に含まれ、実行時のプラグインローダーはありません。ホスト型の組織は独自の拡張機能を追加できません。管理者は `/admin/extensions` で組織ごとに拡張機能を切り替えられます ([管理者ガイド](/ja/admin/extensions/))。

拡張機能を書くには、`packages/integration/extensions/src/sample.ts` のサンプルブロックとテーマから始めます。拡張ポイントを選び、`points.ts` の契約を確認します。ID、バージョン、ライセンス、提供する機能、必要な機能、組織が無効化できるかを宣言します。Web アプリケーションと worker の組み立て箇所に登録し、両方で一致させます。レジストリは作成時と `register` 呼び出し時に各ポイントの規則を確認し、問題があればすべて列挙して登録を拒否します。その際、レジストリの状態は変わりません。拡張機能自身のテストで `extensionContractProblems` が空であることと、無効にすると対象機能が変わることを確認してください。

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