Table of Contents generated automatically
- Impartus API Reference
Base path: http://localhost:8080/api/v1
GET /health/live
Returns process liveness without checking configuration, the upstream service, token caches, the filesystem, or FFmpeg. No authentication required.
Success (200):
{
"success": true,
"data": {
"status": "ok"
},
"meta": {
"command": "health",
"mode": "api"
}
}GET /health/ready
Returns dependency readiness. GET /health is a compatibility alias that returns the same readiness response. No authentication required.
Success (200):
{
"success": true,
"data": {
"status": "ok",
"config": {
"status": "ok"
},
"upstream": {
"status": "reachable"
},
"ffmpeg": {
"status": "available"
}
},
"meta": {
"command": "health",
"mode": "api"
}
}Possible status values:
ok: All dependencies are healthydegraded: One or more dependencies have issues
The config.status will be misconfigured if username, password, or baseUrl are missing.
The upstream.status will be unreachable if the Impartus API cannot be contacted.
The ffmpeg.status will be not_found if FFmpeg is not installed or not in PATH.
Any sub-check can be unknown if readiness probing fails internally; inspect server logs for details.
Because this endpoint is unauthenticated, configuration health is deliberately aggregate: the response does not reveal which credential fields are present or missing.
Healthy and degraded readiness results are cached for 15 seconds and may be that old. Both readiness paths retain HTTP 200 when degraded; clients must inspect data.status.
Protected endpoints require:
Authorization: Bearer <token>Protected routes:
GET /wsGET /coursesGET /lecturesPOST /jobsGET /jobsGET /jobs/{id}DELETE /jobs/{id}
Public routes:
GET /healthGET /health/liveGET /health/readyPOST /auth/login
POST /auth/login
Request:
{
"username": "uid@hyderabad.bits-pilani.ac.in",
"password": "your-password"
}Success (200):
{
"success": true,
"data": {
"token": "...",
"expires": "2025-02-12T12:34:56Z"
}
}Used by auth middleware/login failures and API validation/runtime errors.
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable message",
"details": {}
},
"meta": {
"command": "commandName",
"mode": "api"
}
}Some errors include retry hints when the operation may succeed on retry:
{
"success": false,
"error": {
"code": "UPSTREAM_ERROR",
"message": "Failed to fetch courses from Impartus",
"details": {
"retryable": true,
"retryAfter": 30
}
},
"meta": {
"command": "courses",
"mode": "api"
}
}Retry hints are included for:
LOGIN_FAILED,COURSES_FETCH_FAILED,LECTURES_FETCH_FAILED(502 errors):retryAfter: 30CANCEL_FAILED(500 errors):retryAfter: 10RATE_LIMITED(429 on login):retryAfter: 60
4xx client errors do NOT include retry hints (absence means not retryable).
Used where handlers call respondWithSuccess (login + delete job + health check).
{
"success": true,
"data": {},
"meta": {
"command": "commandName",
"mode": "api"
}
}All handlers wrap responses in {success, data, error, meta} envelope using respondWithEnvelope:
GET /courses→{success: true, data: [...], meta: {command, mode: 'api'}}GET /lectures→{success: true, data: [...], meta: {command, mode: 'api'}}POST /jobs,GET /jobs,GET /jobs/{id}→{success: true, data: {...}, meta: {command, mode: 'api'}}
impartus download --json preserves the standard CLI response envelope and
the existing status, outputPaths, lectureCount, filteredCount, and
totalLectures fields. Its data.artifacts array adds one verified manifest
for every completed lecture download:
{
"schemaVersion": 1,
"artifactId": "impartus:v1:CmQ1iLsQw_Aarxg3Rp4svvDdKX4sJ6R0KFWXn3keTn4",
"lecture": {
"ttid": 12345,
"instituteId": 4,
"subjectId": 67,
"sessionId": 8,
"seqNo": 12,
"topic": "Topic",
"startTime": "upstream value",
"durationSeconds": 3600,
"professor": "Name",
"institute": "Institute",
"noAudio": false
},
"selection": {
"views": "both",
"quality": "720",
"audioOnly": false,
"audioFormat": ""
},
"files": [{
"path": "/absolute/path/to/file.mkv",
"role": "video",
"view": "both",
"container": "mkv",
"bytes": 90604400
}],
"producedAt": "2026-08-08T04:05:06Z",
"producer": {"name": "impartus", "version": "0.1.20"}
}artifactId is a logical identity, not a file-content hash. Version 1 hashes a
canonical binary encoding of the positive institute, subject, session, and
lecture IDs plus the normalized view, quality, and audio choices. Paths,
display text, timestamps, producer version, and file bytes do not affect it.
The optional lowercase files[].sha256 field is the SHA-256 of the completed
file. For newly downloaded lectures, download --json emits the manifest the
downloader built, which omits the field; lectures reused by
--reuse-verified appear with the manifest read back from the library, which
carries it. The library computes the digest when it records a manifest. When
the manifest builder is given a digest, it checks the complete file before
publishing. Rows recorded by older releases may still have an empty digest.
library verify --hash fills any empty row from the bytes on disk; the first
download --reuse-verified fills empty rows named in the latest manifest.
A command fails instead of emitting a completed manifest when a selected
playlist cannot be associated with a unique scoped lecture or when any reported
output is missing, empty, non-regular, or still has a .part suffix.
Subject and session scope come from the explicit CLI selection when redundant
lecture fields are omitted. If a lecture also omits instituteId, the CLI uses
the one unique positive institute already present in the selected batch or the
one unique exact subject/session match from /subjects; missing or conflicting
matches fail before media fetch rather than weakening the version-1 identity.
GET /courses
Returns the authenticated user's courses as a JSON array.
GET /lectures?subjectId={subjectId}&sessionId={sessionId}
Canonical query keys are camelCase: subjectId and sessionId.
Legacy snake_case aliases subject_id and session_id are still accepted for backward compatibility, but error messages and new integrations should use the canonical camelCase names.
Returns lectures as a JSON array.
{
"id": "job-9d7e6db6-0df8-4b6c-9e66-e7269c8931ab",
"subjectId": 678,
"sessionId": 12345,
"startIndex": 1,
"endIndex": 6,
"status": "running",
"progress": 52.5,
"error": "",
"totalLectures": 6,
"completedLectures": 3,
"outputs": ["/path/to/output.mp4"],
"config": {
"quality": "720",
"views": "both",
"audioOnly": false,
"audioFormat": "mp3",
"outputPath": "./downloads",
"enablePipeline": true,
"numWorkers": 4,
"downloadWorkersPerLecture": 4,
"decryptWorkersPerLecture": 4,
"slides": false,
"skipNoAudio": false
},
"createdAt": "2025-02-12T12:00:00Z",
"updatedAt": "2025-02-12T12:01:00Z"
}Notes:
id: opaque identifier beginning withjob-; the current implementation appends a UUID. Store and compare the complete value without parsing it or inferring creation time or ordering.status:pending | running | completed | failed | canceledprogress: float percentage (0-100)totalLectures,completedLectures,outputs,errorare populated as work advancesfilteredLectures: number of selected lectures skipped byskipNoAudio; omitted when zero
POST /jobs
Required fields:
subjectId(int, > 0)sessionId(int, > 0)startIndex(int, >= 1, 1-based)endIndex(int, >= startIndex)
Optional fields:
idempotencyKey(string, max 256 chars): Prevents duplicate job creation. If a job with this key already exists, returns the existing job with 409 Conflict instead of creating a new job. Keys persist across server restarts.
Per-job config overrides are supported in two forms:
- Preferred nested object:
jobConfig - Backward-compatible top-level fields with same names
Legacy top-level override fields are normalized at the request boundary. New clients should send jobConfig.
Supported override keys:
qualityviewsaudioOnlyaudioFormatoutputPathenablePipelinenumWorkersdownloadWorkersPerLecturedecryptWorkersPerLectureskipNoAudio
If jobConfig is provided, top-level compatibility fields are ignored.
Success (201): returns created Job object directly.
Duplicate idempotency key (409 Conflict):
{
"success": true,
"data": {
"job": { ... },
"duplicate": true
},
"meta": {
"command": "createJob",
"mode": "api"
}
}Errors:
INVALID_IDEMPOTENCY_KEY(400): idempotencyKey exceeds 256 charactersINVALID_REQUEST(400): invalid subjectId, sessionId, startIndex, or endIndex
GET /jobs → []Job
GET /jobs/{id} → Job
DELETE /jobs/{id}
Cancels a non-terminal job (pending/running), marks it canceled, and stops execution.
Success (200):
{
"success": true,
"data": {
"id": "job-9d7e6db6-0df8-4b6c-9e66-e7269c8931ab",
"status": "canceled"
}
}Terminal jobs (completed/failed/canceled) return 400 with code JOB_CANNOT_CANCEL.
DELETE is a cancellation operation; it does not delete job history or downloaded media.
Jobs are persisted to a .jobs.json file on disk and survive server restarts.
- Job ID, subjectId, sessionId, startIndex, endIndex
- Job status, progress, outputs, error message
- Job config (quality, views, audioOnly, etc.)
- Idempotency key (if provided)
- CreatedAt and UpdatedAt timestamps
- Credentials (username, password, tokens)
- Runtime context (download progress, active connections)
| Original Status | After Restart |
|---|---|
pending |
Marked as failed (cannot be resumed) |
running |
Marked as failed (cannot resume mid-download) |
completed |
Restored as completed |
failed |
Restored as failed |
canceled |
Restored as canceled |
Idempotency keys are also persisted, so duplicate submissions after restart return the existing job (409 Conflict).
The server retains metadata for the newest 1000 terminal jobs. Pending and running jobs are never pruned while the server is running. On restart, interrupted jobs are first converted to failed and then the 1000-job terminal retention limit is applied. Pruning removes only job metadata and its idempotency-key entry; downloaded media is not deleted.
Persistence writes use atomic file replacement. Progress writes are coalesced, while job creation, cancellation, terminal transitions, and graceful server shutdown are flushed before they are reported as durable.
Route: GET /api/v1/ws
Authentication: Authorization: Bearer <token> is required.
Server emits real-time job events:
job.startedjob.progressjob.completedjob.failedjob.cancelled
job.progress includes execution phase values from the current runtime:
initializinglogging_infetching_lecturesdownloading_slides(when slides are enabled)fetching_playlistsdownloading