Ship media workflowswithout building the pipeline yourself.
Upload a file, start a hosted job, poll or receive a webhook, and download the result. The API complements Konvrt's local-first tools when you need automation, larger files, or backend integration.
Simple job model
Create a job, check status, then download the output when it completes.
Credit-based usage
Only pay for hosted compute when you actually use API or cloud video workloads.
Webhook-ready
Attach a callback URL when polling is not the right fit for your system.
Before you start
API access requires a Pro or Team plan.
Create an API key in the dashboard before making requests.
Use credit packs when your hosted usage grows beyond the included balance.
Core flow
Quick start
# 1. Compress a video
curl -X POST https://your-domain.com/api/v1/compress \
-H "Authorization: Bearer kvrt_your_api_key" \
-F "file=@video.mp4" \
-F "codec=h264" \
-F "quality=23"
# Response: { "job_id": "j_abc123", "status": "pending", "status_url": "/api/v1/status/j_abc123" }
# 2. Check status
curl https://your-domain.com/api/v1/status/j_abc123 \
-H "Authorization: Bearer kvrt_your_api_key"
# 3. Download when complete
curl -O https://your-domain.com/api/v1/download/j_abc123 \
-H "Authorization: Bearer kvrt_your_api_key"Authentication
All requests require an API key in the `Authorization` header. Create a key in the dashboard.
Authorization: Bearer kvrt_your_api_key_hereKeys start with `kvrt_` and are intended for server-side use in your own app or backend.
Limits and credits
Rate limit
Pro and Team plans support 60 requests per minute.
Hosted file size
Video jobs support files up to 2GB.
Included credits
Pro includes 500 credits. Team includes 2,000.
Endpoints
/api/v1/compressUpload and compress a video file. Returns a job ID for tracking.
Request (multipart/form-data)
| Field | Type | Description |
|---|---|---|
file | binary | Video file (required, max 2GB) |
codec | string | h264, h265, av1 (default: h264) |
quality | number | CRF value 18-51 (default: 23) |
method | string | crf, bitrate, size (default: crf) |
resolution | string | e.g. 1920x1080, 1280x720 |
webhook_url | string | URL to POST when job completes |
Response (202 Accepted)
{
"success": true,
"job_id": "j_abc123def456",
"status": "pending",
"status_url": "/api/v1/status/j_abc123def456",
"credits_charged": 5
}/api/v1/status/:jobIdCheck the status of a processing job.
Response (200)
{
"job_id": "j_abc123def456",
"status": "completed",
"progress": 100,
"input": {
"filename": "video.mp4",
"size_bytes": 104857600
},
"output": {
"filename": "video-compressed.mp4",
"size_bytes": 31457280,
"compression_ratio": 70,
"download_url": "/api/v1/download/j_abc123def456",
"expires_at": "2026-04-13T12:00:00Z"
}
}pending | processing | completed | failed/api/v1/download/:jobIdDownload the processed file. Returns the file binary.
Content-Type header. Download links expire 24 hours after job completion./api/v1/usageGet your current plan and credit balance.
Response (200)
{
"plan": "pro",
"credits": {
"balance": 420,
"total_purchased": 500
}
}/api/v1/convertConvert an image between formats using server-side Sharp.
Request (multipart/form-data)
| Field | Type | Description |
|---|---|---|
file | binary | Image file (required, max 50MB) |
format | string | Output format: jpg, png, webp, avif, gif, tiff |
quality | number | 1-100 (default: 80) |
width | number | Resize width in pixels |
height | number | Resize height in pixels |
X-Original-Size, X-Output-Size, and X-Output-Format.Webhooks
Pass a webhook_url when creating a job to receive a POST notification when the job completes or fails.
{
"event": "job.completed",
"job_id": "j_abc123def456",
"status": "completed",
"output": {
"download_url": "/api/v1/download/j_abc123def456",
"size_bytes": 31457280,
"expires_at": "2026-04-13T12:00:00Z"
},
"timestamp": "2026-04-12T12:00:00Z"
}{
"event": "job.failed",
"job_id": "j_abc123def456",
"status": "failed",
"error": "FFmpeg exited with code 1",
"timestamp": "2026-04-12T12:00:00Z"
}Error codes
| Code | Meaning |
|---|---|
400 | Bad request (missing fields) |
401 | Invalid or missing API key |
404 | Job not found |
410 | Download link expired (24h) |
413 | File too large (max 2GB) |
429 | Rate limit exceeded |
Code examples
Node.js
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("file", fs.createReadStream("input.mp4"));
form.append("codec", "h264");
form.append("quality", "23");
const res = await fetch("https://your-domain.com/api/v1/compress", {
method: "POST",
headers: { Authorization: "Bearer kvrt_your_key" },
body: form,
});
const { job_id } = await res.json();
// Poll for completion
let status = "pending";
while (status === "pending" || status === "processing") {
await new Promise((r) => setTimeout(r, 3000));
const check = await fetch(`https://your-domain.com/api/v1/status/${job_id}`, {
headers: { Authorization: "Bearer kvrt_your_key" },
});
const data = await check.json();
status = data.status;
console.log(`Progress: ${data.progress}%`);
}
console.log("Done! Download from:", `/api/v1/download/${job_id}`);Python
import requests
import time
# Upload and compress
with open("input.mp4", "rb") as f:
res = requests.post(
"https://your-domain.com/api/v1/compress",
headers={"Authorization": "Bearer kvrt_your_key"},
files={"file": f},
data={"codec": "h264", "quality": "23"},
)
job_id = res.json()["job_id"]
# Poll for completion
while True:
check = requests.get(
f"https://your-domain.com/api/v1/status/{job_id}",
headers={"Authorization": "Bearer kvrt_your_key"},
)
data = check.json()
print(f"Status: {data['status']} ({data['progress']}%)")
if data["status"] in ("completed", "failed"):
break
time.sleep(3)
# Download result
if data["status"] == "completed":
dl = requests.get(
f"https://your-domain.com/api/v1/download/{job_id}",
headers={"Authorization": "Bearer kvrt_your_key"},
)
with open("output.mp4", "wb") as f:
f.write(dl.content)Media jobs
Use hosted processing when browser-only flows are not enough for your app or customer workflow.
Status and downloads
Track progress, inspect output metadata, and download results from expiring URLs.
Plan-aware billing
Included credits on paid plans with optional packs when your volume expands.