API
Everything in the app is an API. Authenticate with an API key and drive projects, clips, and downloads programmatically.
Authentication
Create a key in Settings → API keys (shown once — store it safely) and send it on every request:
curl https://your-deployment/api/usage \ -H "x-api-key: YOUR_KEY"
Core endpoints
| Method & path | What it does |
|---|---|
POST /api/projects/uploads | Create a project + direct-upload URL. PUT your file to uploadUrl, then… |
POST /api/projects/:id/uploaded | Tell the pipeline the upload finished (starts analysis). |
POST /api/projects/imports | Import by URL: { "url": "…", "contentType": "podcast" } |
GET /api/sessions | List projects (analyses). |
GET /api/sessions/:id/progress | Honest pipeline stage snapshot (SSE stream at …/progress/stream). |
POST /api/sessions/:id/cancel | Cancel an in-flight analysis. |
POST /api/sessions/:id/retry | Re-run a failed/cancelled analysis. |
GET /api/clips?sort=score | List clips (cursor pagination via nextCursor). |
PATCH /api/clips/:id | Studio edits: title, caption, startTs/endTs, captionPreset. |
POST /api/clips/:id/rerender | Re-render the short at the current edits. |
GET /api/clips/:id/download | Signed MP4 download URL (expires; request per download). |
GET /api/usage | Plan, minutes used/included, period reset. |
Example: URL import to downloaded short
# 1. Import
PROJECT=$(curl -s -X POST https://your-deployment/api/projects/imports \
-H "x-api-key: $KEY" -H "content-type: application/json" \
-d '{"url":"https://www.twitch.tv/videos/123456789","contentType":"gaming"}' \
| jq -r .id)
# 2. Poll progress until the stages finish
curl -s https://your-deployment/api/sessions/$PROJECT/progress -H "x-api-key: $KEY"
# 3. List the project's clips
curl -s "https://your-deployment/api/clips?sessionId=$PROJECT&sort=score" \
-H "x-api-key: $KEY"
# 4. Fetch a signed download URL
curl -s https://your-deployment/api/clips/CLIP_ID/download -H "x-api-key: $KEY"Conventions & limits
| Topic | Behavior |
|---|---|
| Errors | Standard HTTP codes with a JSON body: { "message": "human-readable reason" }. |
| Validation | Unknown fields are stripped; invalid fields return 400 with details. |
| Rate limiting | Per-key limits apply (configurable per key); 429 when exceeded. |
| Plan gates | The same minute/concurrency/clip-cap rules as the UI — expect 400s with the limit named. |
| Signed URLs | Playback and download URLs expire; re-request rather than storing them. |
The API surface is the same one the web app uses — it's exercised by the full test suite on every change. An MCP server is also available for agent integrations; see the repository README.