v1.0

QuizVideo API

REST API для платформы видео-квизов: создавайте квизы, где каждый вопрос начинается с видеофрагмента, а ответ собирается после его просмотра.

RESTJSON поверх HTTPS
mp4 / HLSформаты видео
60 fpsсинхронизация вопросов
429rate limit: 100 req/min
Base URL
https://api.quizvideo.example/v1

Как это работает

01
Создайте квизPOST /quizzes — вопросы с полями video.url, video.startAt, video.endAt
02
Старт сессииPOST /sessions — API вернёт playback-токен для плеера
03
Просмотр видеоПлеер играет фрагмент; вопросы «зашиты» во временные метки
04
ОтветPOST /answers — проверка ответа, подсчёт очков, лидерборд

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

Все запросы требуют Bearer-токен в заголовке Authorization. Токены создаются в личном кабинете и бывают двух типов: server (полный доступ) и playback (только чтение вопросов и отправка ответов, выдаётся на одну сессию).

curl
curl https://api.quizvideo.example/v1/quizzes \
  -H "Authorization: Bearer qv_live_9f2K..."
⚠️
Playback-токены одноразовые. Они привязаны к session_id и истекают через 2 часа. Никогда не передавайте server-токен в клиентское приложение.

# Быстрый старт

Минимальный сценарий: создать квиз из одного видео-вопроса и получить его обратно.

Шаг 1 — создание квиза
{
  "title": "Квиз по истории кино",
  "passingScore": 70,
  "questions": [
    {
      "text": "Какой фильм показан в этом фрагменте?",
      "points": 10,
      "video": {
        "url": "https://cdn.quizvideo.example/v/hitchcock.mp4",
        "startAt": 12.5,
        "endAt": 24.0
      },
      "answers": [
        { "text": "Головокружение", "isCorrect": true },
        { "text": "Психо",             "isCorrect": false },
        { "text": "Окно во двор",      "isCorrect": false }
      ]
    }
  ]
}
Шаг 2 — ответ из приложения
const res = await fetch("https://api.quizvideo.example/v1/sessions/sg_4a1/answers", {
  method: "POST",
  headers: {
    "Authorization": "Bearer qv_play_8xK...",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    questionId: "q_77e",
    answerId:   "a_0b2",
    watchedMs:  11480
  })
});

const result = await res.json();
console.log(result.correct, result.score); // true, 10
💡
Поле watchedMs не фикция: сервер сверяет его с длительностью фрагмента и помечает ответ как FLAGGED, если видео было пропущено (см. коды ошибок).

# Видео-вопросы

Ключевая сущность API. Каждый вопрос содержит объект video — фрагмент, который игрок обязан посмотреть перед ответом.

ПолеТипОписание
video.urlstring, requiredСсылка на mp4 или HLS-манифест. Рекомендуем макс. 1080p / 10 Мбит/с.
video.startAtfloat, requiredНачало фрагмента в секундах от начала файла.
video.endAtfloat, requiredКонец фрагмента. Должен быть больше startAt, минимум 1.0 сек.
video.mutedbool, default falseИграть фрагмент без звука (например, для «угадай фильм по кадру»).
video.posterUrlstring, optionalПревью-кадр, показывается до начала воспроизведения.
video.showQuestionAtfloat, optionalМомент внутри фрагмента, когда текст вопроса появляется на экране. По умолчанию — после конца фрагмента.
ℹ️
Время на ответ отсчитывается от конца фрагмента. Поле timeLimit вопроса (сек) стартует после того, как плеер сообщил событие video.ended.

Типы вопросов

ТипКак работает с видео
single_choiceВарианты показываются после фрагмента, выбирается один ответ.
multiple_choiceНесколько верных вариантов, очки — пропорционально.
textСвободный ввод, сервер нормализует регистр и пробелы; опционально fuzzy-match (порог textMatchThreshold).
orderРасставить события из видео в хронологическом порядке.
buzzМожно ответить до конца фрагмента: чем раньше — тем больше очков.

# Эндпоинты

GET /quizzes Список квизов

Возвращает пагинированный список квизов текущего пользователя.

ПараметрТипОписание
limitint, optional1–100, по умолчанию 20.
cursorstring, optionalКурсор пагинации из ответа.
hasVideobool, optionalФильтр: только квизы с видео-вопросами.
200 OK
{
  "data": [
    {
      "id": "qz_9c1",
      "title": "Квиз по истории кино",
      "questionCount": 5,
      "videoSeconds": 86.5,
      "createdAt": "2026-10-21T09:30:00Z"
    }
  ],
  "nextCursor": "cur_x9K2"
}
GET /quizzes/{id} Квиз с вопросами

Полная структура квиза, включая вопросы и объекты video. Поле isCorrect в ответах присутствует только для server-токена.

200 OK
{
  "id": "qz_9c1",
  "title": "Квиз по истории кино",
  "passingScore": 70,
  "questions": [
    {
      "id": "q_77e",
      "type": "single_choice",
      "text": "Какой фильм показан в этом фрагменте?",
      "points": 10,
      "timeLimit": 20,
      "video": {
        "url": "https://cdn.quizvideo.example/v/hitchcock.mp4",
        "startAt": 12.5,
        "endAt": 24.0,
        "muted": false
      },
      "answers": [
        { "id": "a_0b2", "text": "Головокружение", "isCorrect": true },
        { "id": "a_1c3", "text": "Психо", "isCorrect": false }
      ]
    }
  ]
}
POST /quizzes Создать квиз

Создаёт квиз. Видеофайлы нужно предварительно загрузить через POST /uploads и указать полученные URL — прямые ссылки на внешние CDN отклоняются.

⚠️
Валидация видео асинхронная. Ответ вернётся сразу со статусом processing; проверьте video.status через вебхук quiz.video.ready.
201 Created
{
  "id": "qz_9c1",
  "status": "processing",
  "questions": [
    { "id": "q_77e", "video": { "status": "transcoding" } }
  ]
}
POST /quizzes/{id}/sessions Начать сессию

Создаёт игровую сессию и возвращает playback-токен для плеера.

201 Created
{
  "sessionId": "sg_4a1",
  "playbackToken": "qv_play_8xK...",
  "expiresAt": "2026-10-24T18:59:00Z",
  "firstQuestion": "q_77e"
}
POST /sessions/{id}/answers Отправить ответ

Принимает ответ на вопрос. Для типа buzz поле answeredAtMs (позиция в фрагменте) влияет на очки.

ПолеТипОписание
questionIdstring, requiredID вопроса.
answerIdstringДля choice-вопросов.
textstringДля типа text.
watchedMsint, requiredСколько миллисекунд фрагмента реально просмотрено.
answeredAtMsint, optionalТолько для buzz: позиция в видео, когда дан ответ.
200 OK
{
  "correct": true,
  "score": 10,
  "totalScore": 34,
  "nextQuestion": "q_88f"
}
DELETE /quizzes/{id} Удалить квиз

Мягкое удаление: квиз скрывается из списка, видеофайлы удаляются из CDN через 24 часа. Возвращает 204 No Content.

# Модели данных

Quiz

ПолеТипОписание
idstringУникальный идентификатор, префикс qz_.
titlestringНазвание, 1–120 символов.
passingScoreintПроходной балл, % от максимума.
statusstringprocessing | published | archived.
questionsQuestion[]1–50 вопросов.

Question

ПолеТипОписание
idstringПрефикс q_.
typestringsingle_choice | multiple_choice | text | order | buzz.
videoVideo, requiredВидеофрагмент вопроса (см. раздел «Видео-вопросы»).
answersAnswer[]2–6 вариантов для choice-типов.
timeLimitintСекунды на ответ после конца фрагмента, 5–120.
pointsintБаллы за верный ответ, по умолчанию 10.

# Коды ошибок

API использует стандартные HTTP-статусы. Тело ошибки всегда одного формата:

Формат ошибки
{
  "error": {
    "code": "VIDEO_FRAGMENT_INVALID",
    "message": "video.endAt must be greater than video.startAt",
    "requestId": "req_hK29f"
  }
}
СтатусКодПричина
400VIDEO_FRAGMENT_INVALIDendAt ≤ startAt, фрагмент короче 1 сек или выходит за длину файла.
401UNAUTHORIZEDТокен отсутствует, просрочен или не подходит по типу.
403QUIZ_NOT_PUBLISHEDПопытались играть неопубликованный квиз.
404QUIZ_NOT_FOUNDКвиз не существует или удалён.
409VIDEO_NOT_WATCHEDwatchedMs меньше длительности фрагмента — ответ отклонён.
422QUESTION_TIMEOUTОтвет отправлен позже timeLimit.
429RATE_LIMITEDБольше 100 запросов в минуту.
500INTERNALОшибка на стороне сервера, повторите с экспоненциальной задержкой.

# Лимиты

ОграничениеЗначение
Длина видеофрагмента1 сек – 5 мин
Размер видеофайладо 2 ГБ
Форматыmp4 (H.264/AAC), HLS
Вопросов в квизе1–50
Rate limit100 req/мин на токен
Хранение playback-токена2 часа

© 2026 QuizVideo. Вопросы и предложения — api@quizvideo.example