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.
Search
Section titled “Search”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.
Facets and browse
Section titled “Facets and browse”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.
Transcription pipeline
Section titled “Transcription pipeline”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 |
Operations panels
Section titled “Operations panels”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.
Auth summary
Section titled “Auth summary”| 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 |