Aller au contenu
Публичный API · бесплатно

Документация API YA-Planning

Интегрируйте генерацию и просмотр расписаний, управляйте настройкой своих учреждений и получайте события в реальном времени. Полный справочник, примеры и песочница.

Введение

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

Аутентификация

Каждый запрос содержит ключ API в одном из двух заголовков:

X-API-Key: yap_live_xxxxxxxxxxxxxxxxxxxx
# ou
Authorization: Bearer yap_live_xxxxxxxxxxxxxxxxxxxx

Ключ может быть авторизован для нескольких учреждений (корпоративный ключ). В этом случае укажите цель через заголовок X-Etablissement-Id; если разрешено только одно учреждение, оно определяется автоматически. Ключи с областями доступа создаются в консоли.

Среды и песочница

Две среды, различаемые по префиксу ключа:

  • yap_live_… — production: ваши реальные данные; генерация расходует недельную квоту.
  • yap_test_… — sandbox: чтения возвращают набор демонстрационных данных (никогда ваши реальные данные), генерация не расходует квоту, а запись настроек запрещена (SANDBOX_READONLY). Идеально для безопасной разработки.

Области доступа

Каждый ключ несёт подмножество областей доступа; конечная точка отклоняет запрос (403 INSUFFICIENT_SCOPE), если требуемая область отсутствует.

config:readЧитать циклы, классы, предметы, преподавателей, временные интервалы, часовые объёмы.
config:writeСоздавать / изменять / удалять настройку учреждения.
timetables:readПросматривать задачи, читать результаты и опубликованные расписания, экспортировать.
timetables:writeЗапускать генерацию и публиковать расписание.
webhooks:manageСоздавать, просматривать и удалять конечные точки вебхуков.
establishments:manageСоздавать и просматривать собственные учреждения (уровень аккаунта, без X-Etablissement-Id).

Скорость и квоты

У каждого ключа есть ограничение скорости (по умолчанию 60 запр./мин). Ответы содержат:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1783919311   # epoch (s) de réinitialisation

Превышение возвращает 429 RATE_LIMITED с заголовком Retry-After. Генерация расписания дополнительно ограничена недельной квотой тарифа (видна через /me).

Каждый ответ API также содержит заголовок X-Request-Id (идентификатор корреляции) — сообщите его поддержке при инциденте. Примечание: подсчёт скорости в настоящее время применяется на уровне экземпляра; при развёртывании с несколькими экземплярами фактический предел может быть кратен отображаемому значению.

Ошибки

Единообразная оболочка ошибки с requestId для поддержки:

{ "error": "INSUFFICIENT_SCOPE", "message": "Scope requis : config:write.",
  "requestId": "6181762d-…", "requiredScope": "config:write" }
КодerrorПричина
400BAD_REQUESTОтсутствуют или недействительны параметры.
401UNAUTHORIZED / INVALID_API_KEYКлюч отсутствует, недействителен или отозван.
403INSUFFICIENT_SCOPEУ ключа нет требуемой области доступа.
403ETABLISSEMENT_NOT_GRANTEDКлюч не авторизован для запрошенного учреждения.
403SANDBOX_READONLYЗапись запрещена ключом sandbox (только чтение).
402PLAN_UPGRADE_REQUIREDФункция доступна только на платном тарифе (напр. экспорт iCal).
404NOT_FOUNDРесурс не существует или вне вашего учреждения.
409WORKFLOW_ERRORПереход процесса невозможен (напр. публикация черновика).
429RATE_LIMITEDСкорость превышена — повторите после заголовка Retry-After.

Тестировать вживую — без регистрации

Публичные демонстрационные конечные точки (ключ не требуется).

Скачать OpenAPI

Postman: «Import» → «Link» → вставьте /q/openapi?format=json.

Справочник — Аккаунт и интроспекция

GET/me

Сведения о текущем ключе: среда, целевое учреждение, предоставленные области доступа и остаток квоты генерации. Область доступа не требуется.

Ответ
{
  "environment": "LIVE",
  "etablissementId": "61a9…8cb",
  "scopes": ["config:read", "timetables:write"],
  "entitlements": {
    "plan": "PRO",
    "generationsRestantes": -1,
    "resetLe": "2026-07-14T00:00:00Z",
    "maxClassesExport": -1
  }
}
GET/me/etablissement

Публичный профиль целевого учреждения: название, аббревиатура, город, страна, тип, веб-сайт. Область доступа не требуется.

Ответ
{"id":"…","nom":"Groupe Scolaire Les Palmiers","slug":"gs-palmiers","sigle":"GSP","ville":"Abidjan","pays":"CI","type":"PRIVE","siteWeb":"https://…"}
GET/me/usage

Недавнее использование текущего ключа (вызовы и ошибки по дням). Область доступа не требуется.

Параметры:
  • 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 для его настройки и генерации.

POST/account/etablissementsestablishments:manage

Создать учреждение (bucket разработчика, с учётом лимита вашего аккаунта).

Тело
{"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"}
GET/account/etablissementsestablishments:manage

Просмотреть созданные вами учреждения.

Ответ
[{"id":"…","nom":"…","slug":"…","pays":"CI","type":"PRIVE_LAIC"}]

Справочник — Настройка

Педагогическая структура учреждения. Чтение: область config:read. Запись: область config:write (запрещена в sandbox). Только что созданное учреждение уже содержит «Основной цикл».

GET/cyclesconfig:read

Список циклов.

Ответ
[{"id":"…","libelle":"Cycle principal","ordre":0}]
POST/cyclesconfig:write

Создать цикл.

Тело
{"libelle":"Second cycle","ordre":1}
DELETE/cycles/{id}config:write

Удалить цикл.

GET/niveauxconfig:read

Список классов/уровней.

Ответ
[{"id":"…","libelle":"6ème 1","cycleId":"…","effectif":42,"ordre":1}]
POST/niveauxconfig:write

Создать класс.

Тело
{"libelle":"6ème 3","cycleId":"<uuid-cycle>","effectif":40,"ordre":3}
PUT/niveaux/{id}config:write

Изменить класс (частичные поля).

DELETE/niveaux/{id}config:write

Удалить класс.

GET/disciplinesconfig:read

Список предметов.

Ответ
[{"id":"…","libelle":"Mathématiques","code":"MATH","couleur":"#6C5CE7","ordre":1}]
POST/disciplinesconfig:write

Создать предмет.

Тело
{"libelle":"Physique-Chimie","code":"PC","couleur":"#00B894","ordre":5}
PUT/disciplines/{id}config:write

Изменить предмет.

DELETE/disciplines/{id}config:write

Удалить предмет.

GET/professeursconfig:read

Список преподавателей.

Ответ
[{"id":"…","nom":"Koné","prenoms":"Awa","matricule":"P-0142","email":"…","telephone":"…","nombreHeureAutorise":18,"statut":"TITULAIRE","actif":true}]
POST/professeursconfig:write

Создать преподавателя.

Тело
{"nom":"Diarra","prenoms":"Sékou","matricule":"P-0210","email":"s.diarra@ecole.ci","nombreHeureAutorise":18,"statut":"VACATAIRE","actif":true}
PUT/professeurs/{id}config:write

Изменить преподавателя.

DELETE/professeurs/{id}config:write

Удалить преподавателя.

GET/horairesconfig:read

Временные интервалы сетки.

Ответ
[{"id":"…","jour":"MONDAY","heureDebut":"08:00","heureFin":"09:00","estPause":false,"libelle":null}]
POST/horairesconfig:write

Создать интервал (день, HH:mm).

Тело
{"jour":"MONDAY","heureDebut":"08:00","heureFin":"09:00","estPause":false,"libelle":"M1"}
DELETE/horaires/{id}config:write

Удалить интервал.

GET/volumesconfig:read

Часовые объёмы (предмет × цикл).

Ответ
[{"id":"…","cycleId":"…","disciplineId":"…","nombreHeuresObligatoire":4,"minHeuresConsecutives":1,"maxHeuresConsecutives":2}]
POST/volumesconfig:write

Создать часовой объём.

Тело
{"cycleId":"<uuid>","disciplineId":"<uuid>","nombreHeuresObligatoire":4,"minHeuresConsecutives":1,"maxHeuresConsecutives":2}
DELETE/volumes/{id}config:write

Удалить часовой объём.

Справочник — Расписания

Асинхронная генерация (решатель работает в фоновом режиме — опрашивайте статус), публикация и просмотр. В sandbox генерация использует демонстрационный набор и не расходует квоту.

POST/timetables/generatetimetables:write

Запускает генерацию. Возвращает 202 + jobId для опроса. LIVE расходует недельную квоту. Необязательный заголовок Idempotency-Key: одинаковый идентификатор воспроизводит сохранённый ответ (ответ помечен Idempotency-Replayed: true) вместо повторного запуска генерации.

Параметры:
  • Idempotency-Key — заголовок (необязательно) — ключ идемпотентности на стороне LIVE
Тело
{"durationMinutes": 5}
Ответ
{"jobId":"…","status":"SOLVING_SCHEDULED"}
GET/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}
GET/timetables/jobs/{jobId}timetables:read

Статус задачи.

GET/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}]}
POST/timetables/jobs/{jobId}/publishtimetables:write

Публикует расписание (процесс → PUBLIE). Запускает событие вебхука timetable.published.

GET/timetables/published/latesttimetables:read

Последнее опубликованное расписание учреждения.

GET/timetables/published/{jobId}/classestimetables:read

Названия классов в опубликованном расписании.

Ответ
{"classes":["6ème 1","6ème 2","5ème 1"]}
GET/timetables/published/{jobId}/classe/{niveau}timetables:read

Уроки класса из опубликованного расписания.

GET/timetables/jobs/{jobId}/export.icstimetables:read

Экспорт iCalendar (text/calendar). Только для тарифа Pro → иначе 402.

Параметры:
  • niveau — фильтр по классу
  • professeur — фильтр по преподавателю
GET/timetables/jobs/{jobId}/export.pdftimetables:read

Экспорт PDF (application/pdf) — весь поток, по классу или по преподавателю.

Параметры:
  • mode — all | class | teacher
  • niveau — обязательно, если mode=class
  • professeur — обязательно, если mode=teacher

Справочник — Webhooks

Получайте подписанные события. Область webhooks:manage. Секрет возвращается только при создании (или после ротации). События: timetable.job.completed, timetable.job.failed, timetable.published, webhook.test. Каждая доставка подписывается (HMAC-SHA256) и повторяется до 5 раз при сбое. URL проверяется против SSRF (внутренние/приватные цели отклоняются).

GET/webhookswebhooks:manage

Список конечных точек.

POST/webhookswebhooks:manage

Создать конечную точку. Возвращает секрет подписи (сохраните его).

Тело
{"url":"https://exemple.com/webhooks/yap","events":["timetable.published","timetable.job.completed"]}
Ответ
{"endpoint":{"id":"…","url":"…","events":["timetable.published"],"active":true},"secret":"whsec_…"}
DELETE/webhooks/{id}webhooks:manage

Удалить конечную точку.

GET/webhooks/{id}/deliverieswebhooks:manage

Журнал доставок (статус, код HTTP, попытки).

POST/webhooks/{id}/rotatewebhooks:manage

Перегенерировать секрет подписи (возвращается один раз).

Ответ
{"endpoint":{"id":"…","url":"…"},"secret":"whsec_…"}
POST/webhooks/{id}/testwebhooks:manage

Отправить событие webhook.test на конечную точку (202 + status queued).

POST/webhooks/deliveries/{deliveryId}/replaywebhooks:manage

Повторить прошлую доставку (202 + status queued).

Справочник — Демо (публично, без ключа)

Публичные неаутентифицированные конечные точки для изучения формы ответов.

GET/api/v1/public/api-demo/preview

Обзор демонстрационного учреждения (циклы, классы, предметы, преподаватели, интервалы).

GET/api/v1/public/api-demo/sample-timetable

Пример уроков (форма созданного расписания).

Webhooks — проверка подписи

Каждая доставка — это JSON POST с заголовками X-Webhook-Event, X-Webhook-Timestamp и X-Webhook-Signature = HMAC-SHA256(timestamp + "." + body, secret). Проверяйте подпись и свежесть timestamp (менее 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; ротация / тест / повтор вебхуков; событие timetable.job.failed; заголовок X-Request-Id; пагинация списков настройки; истечение срока и ограничение по IP для ключей; проверка URL вебхуков против SSRF.
  • 2026-06 — Запуск публичного API v1: ключи с областями доступа, настройка, генерация и публикация расписаний, подписанные вебхуки, песочница, заголовки квот.

Готовы к интеграции?

Создайте ключ sandbox за 30 секунд и сделайте первый вызов.

Открыть консоль API