Skip to content

API reference

Base URL: https://kalelm-api.mohanad.xyz/api. Collections (/materials, /transcripts, /sheikhs, …) follow Payload’s REST conventions: ?limit=&page=&depth=&where[field][equals]=&select[field]=true&locale=. Everything below is custom.

POST /search — JSON body.

Field Values Notes
q string required unless mode is keyword
mode keyword · hybrid · semantic default keyword from the API; the site defaults to hybrid
scope transcripts · titles titles is always a literal match
sort relevance · date sorts
type[], sheikhId[], seriesId[] filters
since unix seconds results on or after
language ar (default) · en · ur which language’s material
limit, page 1–50, ≥1 transcript results page over a grouped window, not the whole archive

Response: query, mode, degraded, matchCount, matchDocs, tookMs, scope, page, limit, totalPages, results[], facets. degraded is set to the requested mode when keyword results were served instead. matchCount/matchDocs are null for vector modes on purpose.

  • GET /facets?type=&language=&sheikh=&series=&year=&hasTranscript=&locale= — counts by sheikh, series, year and transcript presence for the current filters. Cached 5 min per query string.
  • GET /tree?order=type,sheikh,series&path=&language=&offset=&limit= — one level of the browse tree; ?q= searches it. Cached 5 min.

Admin session required for the first two; the rest accept Authorization: Bearer $CRON_SECRET (or an admin session).

Endpoint Body Returns
GET /pipeline/stats counts by status, backlog, last 24 h, active workers, recent failures, settings, local worker
POST /pipeline/control {action: enqueue, limit?} · retryFailed · {requeue, id} · {pause, paused} · {postEdit, enabled} · startWorker · stopWorker action result
POST /pipeline/claim {worker, limit?} {jobs: [{id, materialId, title, audioUrl, language, duration, postEdit, postEditModel}], paused}
POST /pipeline/heartbeat {id, stage?} {ok}false means the job is no longer yours
POST /pipeline/complete {id, cues: [{start, text}], stats?, language?} or {id, error} `{status: done
  • GET /durations/stats, POST /durations/run {kind: youtube|mp3} or {stop: true} — the duration backfill.
  • GET /indexing/stats — progress of the search index builds.

All three panels are admin-only and read by /admin/durations, /admin/indexing, /admin/transcription.

Caller How
Site anonymous REST; read access is public for published content
Admin panel Payload session cookie; roles admin / editor
Workers, cron Authorization: Bearer $CRON_SECRET