YA-Planning API ドキュメント
時間割の生成と閲覧を統合し、学校の設定を管理し、リアルタイムでイベントを受信できます。完全なリファレンス、サンプル、サンドボックス。
はじめに
API は REST 形式、JSON、バージョン管理されています。すべての業務リソースはプレフィックス /api/v1/pub/v1 の下にあります。公開デモのエンドポイントは /api/v1/public/api-demo の下にあります。
- Base URL:
https://votre-domaine/api/v1/pub/v1 - 形式:リクエストとレスポンスは
application/json(ICS/PDF エクスポートを除く)。 - バージョニング:バージョンはパスに含まれます(
/v1)。後方互換のある追加ではバージョンは変わりません。 - CORS:公開 API はサードパーティのブラウザアプリケーションに開かれています(Cookie なし)。
認証
各リクエストは、2つのヘッダーのいずれかに API キーを含めます:
X-API-Key: yap_live_xxxxxxxxxxxxxxxxxxxx
# ou
Authorization: Bearer yap_live_xxxxxxxxxxxxxxxxxxxx1つのキーを複数の学校に対して許可できます(エンタープライズキー)。その場合は X-Etablissement-Id ヘッダーで対象を指定してください。許可された学校が1つだけの場合は自動的に判別されます。キーはスコープ付きで コンソール から作成します。
環境とサンドボックス
キーのプレフィックスで区別される2つの環境:
yap_live_…— 本番:実際のデータ。生成は週間クォータを消費します。yap_test_…— サンドボックス:読み取りはデモデータのセットを返し(実データは決して返しません)、生成はクォータから消費されず、設定の書き込みは拒否されます(SANDBOX_READONLY)。リスクなく開発するのに最適です。
スコープ
各キーはスコープのサブセットを持ちます。必要なスコープが不足している場合、エンドポイントは拒否します(403 INSUFFICIENT_SCOPE)。
config:read | サイクル、クラス、科目、教員、コマ、授業時数を読み取ります。 |
config:write | 学校の設定を作成 / 変更 / 削除します。 |
timetables:read | ジョブの一覧表示、結果と公開済み時間割の読み取り、エクスポート。 |
timetables:write | 生成の実行と時間割の公開。 |
webhooks:manage | Webhook エンドポイントの作成、一覧表示、削除。 |
establishments:manage | 自分の学校の作成と一覧表示(アカウントレベル、X-Etablissement-Id なし)。 |
レート制限とクォータ
各キーにはレート制限があります(デフォルト 60 req/min)。レスポンスには次が含まれます:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1783919311 # epoch (s) de réinitialisation超過すると Retry-After ヘッダー付きで 429 RATE_LIMITED を返します。時間割の生成はさらにプランの週間クォータの対象となります(/me で確認可能)。
API のすべてのレスポンスには X-Request-Id ヘッダー(相関 ID)も含まれます — 障害時にはサポートへお伝えください。注:レート集計は現在インスタンスごとに適用されています。複数インスタンスのデプロイでは、実効的な制限が表示値の倍数になる場合があります。
エラー
サポート用の requestId を含む、統一されたエラーエンベロープ:
{ "error": "INSUFFICIENT_SCOPE", "message": "Scope requis : config:write.",
"requestId": "6181762d-…", "requiredScope": "config:write" }| コード | error | 原因 |
|---|---|---|
| 400 | BAD_REQUEST | パラメータが不足または無効です。 |
| 401 | UNAUTHORIZED / INVALID_API_KEY | キーが存在しない、無効、または失効しています。 |
| 403 | INSUFFICIENT_SCOPE | キーに必要なスコープがありません。 |
| 403 | ETABLISSEMENT_NOT_GRANTED | キーは要求された学校に対して許可されていません。 |
| 403 | SANDBOX_READONLY | サンドボックスキーでは書き込みできません(読み取り専用)。 |
| 402 | PLAN_UPGRADE_REQUIRED | 有料プラン専用の機能です(例:iCal エクスポート)。 |
| 404 | NOT_FOUND | リソースが存在しないか、貴校の範囲外です。 |
| 409 | WORKFLOW_ERROR | ワークフローの遷移ができません(例:下書きの公開)。 |
| 429 | RATE_LIMITED | レート超過 — Retry-After ヘッダーの後に再試行してください。 |
その場でテスト — 登録不要
公開デモのエンドポイント(キー不要)。
Postman:「Import」→「Link」→ /q/openapi?format=json を貼り付け。
リファレンス — アカウントとイントロスペクション
/me現在のキーの詳細:環境、対象の学校、付与されたスコープ、残りの生成クォータ。スコープ不要。
{
"environment": "LIVE",
"etablissementId": "61a9…8cb",
"scopes": ["config:read", "timetables:write"],
"entitlements": {
"plan": "PRO",
"generationsRestantes": -1,
"resetLe": "2026-07-14T00:00:00Z",
"maxClassesExport": -1
}
}/me/etablissement対象の学校の公開プロフィール:名称、略称、都市、国、種類、ウェブサイト。スコープ不要。
{"id":"…","nom":"Groupe Scolaire Les Palmiers","slug":"gs-palmiers","sigle":"GSP","ville":"Abidjan","pays":"CI","type":"PRIVE","siteWeb":"https://…"}/me/usage現在のキーの最近の使用状況(1日あたりの呼び出しとエラー)。スコープ不要。
days— 日数のウィンドウ(デフォルト30、最大90)
{"apiKeyId":"…","days":30,"daily":[{"day":"2026-07-12","calls":128,"errors":3}]}リファレンス — アカウント — 学校
アカウントレベルのプロビジョニング:X-Etablissement-Id ヘッダーなしで自分の学校を作成します(/account パスは学校に紐付きません)。スコープ establishments:manage。作成時、呼び出し元のキーは新しい学校に対して自動的に ACTIVE グラントを受け取ります — その後は X-Etablissement-Id を使って設定・生成してください。
/account/etablissementsestablishments:manage学校を作成します(開発者バケット、アカウントの上限の対象)。
{"nom":"Groupe Scolaire Les Palmiers","type":"PRIVE_LAIC","pays":"CI"}{"id":"…","nom":"Groupe Scolaire Les Palmiers","slug":"gs-les-palmiers","pays":"CI","type":"PRIVE_LAIC"}/account/etablissementsestablishments:manage作成した学校を一覧表示します。
[{"id":"…","nom":"…","slug":"…","pays":"CI","type":"PRIVE_LAIC"}]リファレンス — 設定
学校の教育構造。読み取り:スコープ config:read。書き込み:スコープ config:write(サンドボックスでは禁止)。新規作成した学校には、すでに「メインサイクル」が含まれています。
/cyclesconfig:readサイクルの一覧。
[{"id":"…","libelle":"Cycle principal","ordre":0}]/cyclesconfig:writeサイクルを作成。
{"libelle":"Second cycle","ordre":1}/cycles/{id}config:writeサイクルを削除。
/niveauxconfig:readクラス / 学年の一覧。
[{"id":"…","libelle":"6ème 1","cycleId":"…","effectif":42,"ordre":1}]/niveauxconfig:writeクラスを作成。
{"libelle":"6ème 3","cycleId":"<uuid-cycle>","effectif":40,"ordre":3}/niveaux/{id}config:writeクラスを変更(部分フィールド)。
/niveaux/{id}config:writeクラスを削除。
/disciplinesconfig:read科目の一覧。
[{"id":"…","libelle":"Mathématiques","code":"MATH","couleur":"#6C5CE7","ordre":1}]/disciplinesconfig:write科目を作成。
{"libelle":"Physique-Chimie","code":"PC","couleur":"#00B894","ordre":5}/disciplines/{id}config:write科目を変更。
/disciplines/{id}config:write科目を削除。
/professeursconfig:read教員の一覧。
[{"id":"…","nom":"Koné","prenoms":"Awa","matricule":"P-0142","email":"…","telephone":"…","nombreHeureAutorise":18,"statut":"TITULAIRE","actif":true}]/professeursconfig:write教員を作成。
{"nom":"Diarra","prenoms":"Sékou","matricule":"P-0210","email":"s.diarra@ecole.ci","nombreHeureAutorise":18,"statut":"VACATAIRE","actif":true}/professeurs/{id}config:write教員を変更。
/professeurs/{id}config:write教員を削除。
/horairesconfig:readグリッドのコマ。
[{"id":"…","jour":"MONDAY","heureDebut":"08:00","heureFin":"09:00","estPause":false,"libelle":null}]/horairesconfig:writeコマを作成(曜日、HH:mm)。
{"jour":"MONDAY","heureDebut":"08:00","heureFin":"09:00","estPause":false,"libelle":"M1"}/horaires/{id}config:writeコマを削除。
/volumesconfig:read授業時数(科目 × サイクル)。
[{"id":"…","cycleId":"…","disciplineId":"…","nombreHeuresObligatoire":4,"minHeuresConsecutives":1,"maxHeuresConsecutives":2}]/volumesconfig:write授業時数を作成。
{"cycleId":"<uuid>","disciplineId":"<uuid>","nombreHeuresObligatoire":4,"minHeuresConsecutives":1,"maxHeuresConsecutives":2}/volumes/{id}config:write授業時数を削除。
リファレンス — 時間割
非同期の生成(ソルバーはバックグラウンドで実行 — ステータスを問い合わせてください)、公開、閲覧。サンドボックスでは、生成はデモセットを使用し、クォータから消費されません。
/timetables/generatetimetables:write生成を実行します。202 と問い合わせ用の jobId を返します。LIVE では週間クォータを消費します。任意の Idempotency-Key ヘッダー:同じ識別子は、生成を再実行する代わりに、記憶されたレスポンスを再送します(レスポンスに Idempotency-Replayed: true が付きます)。
Idempotency-Key— ヘッダー(任意)— LIVE 側の冪等性キー
{"durationMinutes": 5}{"jobId":"…","status":"SOLVING_SCHEDULED"}/timetables/jobstimetables:readジョブのページネーション付き一覧。
page— ページのインデックス(デフォルト0)size— サイズ(デフォルト25、最大100)
{"items":[{"jobId":"…","name":"…","status":"SOLVING_ENDED","workflowStatus":"BROUILLON","feasible":true,"hardScore":0,"softScore":-42,"createdAt":"…"}],"total":7,"page":0,"size":25}/timetables/jobs/{jobId}timetables:readジョブのステータス。
/timetables/jobs/{jobId}/resulttimetables:read結果:授業の一覧(status = SOLVING_ENDED になったら)。
{"jobId":"…","status":"SOLVING_ENDED","feasible":true,"lessons":[{"id":"1","matiere":"Maths","niveau":"6ème 1","professeur":"M. Koné","jour":"MONDAY","debut":"08:00:00","fin":"09:00:00","couleur":"#6C5CE7","niveauOrdre":1,"verrouille":false}]}/timetables/jobs/{jobId}/publishtimetables:write時間割を公開します(ワークフロー → PUBLIE)。webhook イベント timetable.published を発火します。
/timetables/published/latesttimetables:read学校の最新の公開済み時間割。
/timetables/published/{jobId}/classestimetables:read公開済み時間割に含まれるクラスの名称。
{"classes":["6ème 1","6ème 2","5ème 1"]}/timetables/published/{jobId}/classe/{niveau}timetables:read公開済み時間割の1クラスの授業。
/timetables/jobs/{jobId}/export.icstimetables:readiCalendar エクスポート(text/calendar)。Pro プラン専用 → それ以外は 402。
niveau— クラスで絞り込みprofesseur— 教員で絞り込み
/timetables/jobs/{jobId}/export.pdftimetables:readPDF エクスポート(application/pdf)— 全体、クラス別、または教員別。
mode— all | class | teacherniveau— mode=class の場合は必須professeur— mode=teacher の場合は必須
リファレンス — Webhook
署名付きイベントを受信します。スコープ webhooks:manage。シークレットは作成時(またはローテーション後)のみ返されます。イベント:timetable.job.completed、timetable.job.failed、timetable.published、webhook.test。各配信は署名され(HMAC-SHA256)、失敗時は最大5回まで再送されます。URL は SSRF に対して検証されます(内部・プライベートの宛先は拒否)。
/webhookswebhooks:manageエンドポイントの一覧。
/webhookswebhooks:manageエンドポイントを作成します。署名シークレットを返します(保管してください)。
{"url":"https://exemple.com/webhooks/yap","events":["timetable.published","timetable.job.completed"]}{"endpoint":{"id":"…","url":"…","events":["timetable.published"],"active":true},"secret":"whsec_…"}/webhooks/{id}webhooks:manageエンドポイントを削除。
/webhooks/{id}/deliverieswebhooks:manage配信ログ(ステータス、HTTP コード、試行回数)。
/webhooks/{id}/rotatewebhooks:manage署名シークレットを再生成します(1回のみ返されます)。
{"endpoint":{"id":"…","url":"…"},"secret":"whsec_…"}/webhooks/{id}/testwebhooks:manageエンドポイントに webhook.test イベントを送信します(202 + status queued)。
/webhooks/deliveries/{deliveryId}/replaywebhooks:manage過去の配信を再送します(202 + status queued)。
リファレンス — デモ(公開、キー不要)
レスポンスの形式を確認するための、認証不要の公開エンドポイント。
/api/v1/public/api-demo/previewデモ学校のプレビュー(サイクル、クラス、科目、教員、コマ)。
/api/v1/public/api-demo/sample-timetable授業の例(生成された時間割の形式)。
Webhook — 署名の検証
各配信は、ヘッダー X-Webhook-Event、X-Webhook-Timestamp、X-Webhook-Signature = HMAC-SHA256(timestamp + "." + body, secret) を含む POST JSON です。リプレイを防ぐため、署名とタイムスタンプの新しさ(5分以内)を検証してください。イベント:timetable.published、timetable.job.completed、timetable.job.failed、webhook.test。
POST https://votre-app/webhook
X-Webhook-Event: timetable.published
X-Webhook-Timestamp: 1712345678
X-Webhook-Signature: 9f86d081…
{ "event":"timetable.published", "jobId":"…", "etablissementId":"…", "occurredAt":"…" }import crypto from "crypto";
// Express — vérifier la signature d'un webhook YA-Planning
app.post("/webhooks/yap", express.raw({ type: "*/*" }), (req, res) => {
const ts = req.header("X-Webhook-Timestamp");
const sig = req.header("X-Webhook-Signature");
const body = req.body.toString("utf8");
const expected = crypto.createHmac("sha256", process.env.YAP_WEBHOOK_SECRET)
.update(`${ts}.${body}`).digest("hex");
// fraîcheur (anti-rejeu) : < 5 min
const fresh = Math.abs(Date.now()/1000 - Number(ts)) < 300;
if (!fresh || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
return res.sendStatus(400);
const event = JSON.parse(body); // { event, jobId, etablissementId, occurredAt }
res.sendStatus(200);
});コード例
# Vérifier ses droits
curl https://votre-domaine/api/v1/pub/v1/me \
-H "X-API-Key: yap_live_xxxxxxxxxxxx"
# Générer un EDT puis suivre le job
JOB=$(curl -s -X POST .../api/v1/pub/v1/timetables/generate \
-H "X-API-Key: yap_live_xxxx" -H "Content-Type: application/json" \
-d '{"durationMinutes":5}' | jq -r .jobId)
curl .../api/v1/pub/v1/timetables/jobs/$JOB \
-H "X-API-Key: yap_live_xxxx"バージョンと非推奨化
API はパスでバージョン管理されています(/api/v1/pub/v1/…)。フィールドやエンドポイントは後方互換の形で追加します。これらの追加は破壊的変更ではないため、寛容にコーディングしてください(未知のフィールドは無視する)。破壊的変更が生じる場合は、新しいメジャーバージョンとして、最低90日前の予告を行い、Deprecation レスポンスヘッダーと以下の変更履歴で通知します。
2026-07— 開発者アカウントとダッシュボード。アカウントレベルのプロビジョニング(POST /account/etablissements、スコープestablishments:manage)。/cyclesエンドポイント。PDF エクスポートmode=teacher。2026-07— 生成時の Idempotency-Key。/me/etablissement、/me/usageエンドポイント。Webhook のローテーション / テスト / 再送。timetable.job.failedイベント。X-Request-Idヘッダー。設定一覧のページネーション。キーの有効期限と IP 制限。Webhook URL の SSRF 対策バリデーション。2026-06— 公開 API v1 のリリース:スコープ付きキー、設定、時間割の生成と公開、署名付き Webhook、サンドボックス、クォータヘッダー。
