Помощь · Интеграции

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

Публичные маршруты Latorn для учётных записей, обучения и преподавательских инструментов. Каждый раздел можно читать отдельно.

Здесь описаны только пользовательские и преподавательские интеграции. Служебные операции платформы в публичный справочник не входят.

Справочник API

Подключение внешнего редактора

Безопасный Bearer-токен для загрузки материалов из CLI, серверного скрипта или настольного редактора.

Маршруты раздела

Метод Маршрут Доступ Назначение
GET /api/account/api-tokens Нужна сессия преподавателя Получить список своих подключений и курсов для привязки.
POST /api/account/api-tokens Нужна сессия преподавателя Создать токен; секрет возвращается только один раз.
DELETE /api/account/api-tokens/{id} Нужна сессия преподавателя Немедленно отозвать своё подключение.

Где создать токен

Откройте Настройки → API-токены (/profile/security?section=api). Укажите название подключения, выберите курсы, права и срок действия. Секрет показывается один раз: Latorn хранит только его SHA-256-хеш.

Для выбранных курсов форма показывает доступные вам права. Редактор материалов не получает управление настройками и ценой, а управляющий не получает анализ продаж. При выборе нескольких курсов право должно быть доступно в каждом из них. Если сочетание не подходит, исключите курс или нажмите «Убрать недоступные права». Токен не расширяет вашу роль в команде курса.

Для каждого редактора или устройства лучше создавать отдельный токен. Тогда одно подключение можно отозвать, не останавливая остальные.

Авторизация запроса

export LATORN_API_TOKEN='latorn_pat_…'

curl https://latorn.ru/api/courses?page=1 \
  -H "Authorization: Bearer $LATORN_API_TOKEN"
const baseUrl = "https://latorn.ru";
const token = process.env.LATORN_API_TOKEN;

async function latorn(path: string, init: RequestInit = {}) {
  const response = await fetch(baseUrl + path, {
    ...init,
    headers: { ...init.headers, Authorization: `Bearer ${token}` },
  });

  if (!response.ok) {
    const payload = await response.json().catch(() => null);
    throw new Error(payload?.error?.message ?? `HTTP ${response.status}`);
  }

  return response;
}

Если заголовок Authorization присутствует, но токен неверен, истёк или отозван, Latorn возвращает 401 и не подменяет его cookie-сессией.

Права токена

  • COURSES_READ — читать сведения о выбранных курсах;
  • COURSES_CREATE — создавать черновики курсов;
  • COURSES_WRITE — менять настройки курса;
  • COURSES_PUBLISH — запросить одноразовую ссылку на публикацию; решение подтверждает человек внутри Latorn;
  • CONTENT_READ — читать секции, уроки и преподавательские блоки шагов;
  • CONTENT_WRITE — создавать, менять и удалять секции, уроки и шаги;
  • MEDIA_WRITE — загружать обложки, изображения и аудио;
  • REVENUE_READ — читать только агрегированную аналитику продаж без покупателей и ID операций;
  • PROMOS_WRITE — читать и атомарно массово сохранять промокоды только выбранных курсов с актуальным course:manage;
  • TASK_SEO_READ — только для актуального администратора: постранично просматривать условия задач всех курсов без скрытых тестов и ответов. Публикацию это право не разрешает;
  • BROADCAST_DRAFTS_WRITE — только для актуального администратора: читать и готовить собственные черновики рассылок, выбирать встроенный сегмент, фильтры курсов и ограничение «Только бесплатники» (поле freeUsersOnly). Оно исключает покупателей и пользователей с платными курсами. Получатели доступны только для проверки администратору в интерфейсе.

Токен — только верхняя граница доступа. При каждом запросе Latorn заново проверяет владельца или роль в команде курса. Если преподавателя удалили из команды, старый токен сразу перестанет работать. Даже расширенная роль аккаунта не даёт токену автоматический доступ к чужим курсам.

Токен не даёт управлять платежами, возвратами, выплатами, пользователями или настройками аккаунта. REVENUE_READ открывает только агрегированную аналитику выбранных курсов. PROMOS_WRITE не меняет цену или checkout и при отключении кода сохраняет историю применений. BROADCAST_DRAFTS_WRITE разрешает выбрать встроенный consent-only сегмент и course filters/exclusions в собственном DRAFT, но не возвращает получателей или PII и не открывает поиск, предпросмотр аудитории, тест, отправку или планирование. Перед отправкой администратор проверяет обновлённое preview и явно подтверждает send в Latorn. Прямое изменение статуса публикации по Bearer запрещено: COURSES_PUBLISH создаёт запрос, который владелец токена подтверждает в Latorn. Удаление целого курса через токен отключено.

Опубликованные школьные курсы видны в общем каталоге. В публичном GET /api/courses доступны фильтры catalog=school, schoolSubject и schoolTrack; в каталоге пункт «Школьникам» отбирает курсы с заданным школьным предметом. Название и теги не используются для исключения курсов.

Последовательность импорта

  1. Получите курс через GET /api/courses или создайте черновик через POST /api/courses.
  2. Создайте секцию через POST /api/sections.
  3. Создайте урок через POST /api/lessons.
  4. Загрузите файлы, если они нужны.
  5. Создайте шаги через POST /api/steps.

Новый курс, созданный токеном с правом COURSES_CREATE, автоматически добавляется в область действия этого токена.
Публичный список GET /api/courses для гостя или ученика по умолчанию использует sort=recommended: учитывает покупки за всё время, интересы и разнообразие. Сортировки popular, newest, updated, price_asc и price_desc сохраняются. Авторские списки, свои записи, административный обзор и Bearer-запросы сохраняют прежний порядок по популярности и область доступа; recommended в этих списках эквивалентен popular. Внутренние показатели ранжирования не возвращаются.
POST /api/courses принимает отдельные nullable-поля seoTitle и seoDescription: до 120 и 160 символов соответственно. Они меняют только поисковые, Open Graph, Twitter и структурированные метаданные; видимые название, описание и краткое описание курса остаются прежними. В PUT /api/courses/[id] значение null очищает override и возвращает прежний автоматический fallback. Переименование курса не меняет его slug. Явный новый slug разрешён для черновика или курса без индексируемых уроков; опубликованный курс с индексируемым уроком отвечает 409 COURSE_SLUG_LOCKED.

Урок принимает slug, seoTitle, seoDescription и isIndexable в POST /api/lessons и PUT /api/lessons/[id]. Slug нормализуется в kebab-case и уникален внутри курса; nullable-поля очищаются через null. Индексацию можно включить только для PUBLIC-урока с корректным slug. После этого опубликованный урок получает публичный адрес /courses/[courseSlug]/lessons/[lessonSlug]; учебный раннер /learn остаётся закрытым от индексации.

Загрузка файла

При загрузке обложки или изображения урока через Bearer-токен обязательно передайте courseId. Не задавайте Content-Type вручную: FormData сам добавит boundary.

const form = new FormData();
form.set("courseId", courseId);
form.set("file", file);

await latorn("/api/uploads/lesson-media", { method: "POST", body: form });

Обложки и изображения урока принимают PNG, JPEG, WebP и SVG. SVG ограничен 2 МБ, проверяется на активные и внешние конструкции и сохраняется только как PNG; исходный XML не публикуется. Аватары и вложения на проверку SVG не принимают.

Файлы для скачивания учеником загружаются отдельно, после создания шага: POST /api/steps/[id]/attachments, multipart-поле file. Поддерживаются ZIP/RAR/7Z/TAR/GZ/BZ2/XZ, PDF, DOC/DOCX/XLS/XLSX/PPT/PPTX/ODT/ODS/ODP, PNG/JPEG/WebP, IPYNB, CSV/TSV/Parquet/SQLite, HTML/XML/SVG, текст, исходники и конфигурации, включая Dockerfile и другие файлы без расширения. Полный список расширений — в API Reference. Текстовые файлы могут быть в любой кодировке, включая Windows-1251 и UTF-16: байты не изменяются. Лимиты: до 25 МБ на файл, 10 файлов на шаг и 250 МБ на курс. Для PAT нужны CONTENT_WRITE, привязка к курсу и актуальное право редактирования; курс определяется по шагу, поэтому courseId в форме не нужен. Архивы хранятся без распаковки; HTML, SVG и исходники скачиваются как файлы и не исполняются. Список файлов доступен через GET /api/steps/[id]/attachments с CONTENT_READ; скачивание учеником идёт по downloadUrl после проверки доступа к шагу.

Ошибки доступа

  • INVALID_API_TOKEN — формат или секрет неверен;
  • API_TOKEN_EXPIRED — срок действия закончился;
  • API_TOKEN_REVOKED — подключение отозвано;
  • API_TOKEN_SCOPE_REQUIRED — не выдано нужное право;
  • COURSE_ACCESS_DENIED или 404 — курс не привязан либо текущие права пользователя изменились.

Персональный токен рассчитан на backend, CLI и desktop. Для браузерного редактора на другом домене используйте backend-proxy и храните секрет только на сервере.