Streamlet Platform Documentation
RESTful API Reference
Use Streamlet directly over HTTP when you want full control over upload, processing, captions, image hosting, storage, and backend workflows.
Templates
Use the official Streamlet template repository when you want a faster starting point for frontend apps or backend REST API services. Open Streamlet-Templates.
| Template | Stack | Purpose |
|---|---|---|
| Next.js Video Upload | Next.js 16 | Frontend starter for Streamlet SDK-based upload and processing flows. |
| Next.js Image Upload | Next.js 16 | Frontend starter for image hosting and CDN delivery. |
| Next.js Player | Next.js 16 | Playback-focused Streamlet player starter. |
| Node.js Express REST API | Node.js / Express | Proxy Streamlet REST API routes from an Express backend. |
| Go REST API | Go | Streamlet REST wrapper for Go services. |
| Python REST API | Python / FastAPI | FastAPI example for Streamlet uploads and status endpoints. |
| Rust REST API | Rust / Axum | Rust backend starter for Streamlet REST integrations. |
| Java REST API | Java / Spring Boot | Spring Boot backend starter for Streamlet APIs. |
Authentication
Streamlet API-key routes require both the API key and the account number. These match the middleware already used in the main Streamlet backend.
x-streamlet-api-key and x-streamlet-account-number must be sent on every protected request.
Upload Video
POST to /api-key/start-video-processing with multipart form data. Upload the source video, set the title, and optionally enable captions, original-file retention, and high-resolution output. The server responds immediately with a videoId — use the Status API to poll for completion.
Use the uploadType field to choose how the file is handled.uploadType=streaming (the default) runs the full processing pipeline: transcoding into an adaptive HLS ladder, thumbnails and optional captions.uploadType=private uploads the file directly to storage with no processing — the response returns status="completed" right away with a streamUrl pointing at the stored file. All processing options below are ignored for private uploads.
Pass enable2kOutput=true (Builder and Pro plans) to add a 1440p (2K) rendition to the HLS adaptive ladder. Pass enable4kOutput=true (Pro plan only) to add a 2160p (4K) rendition. Both flags are silently ignored on plans that do not support them.
Create processing job
JavaScript
const formData = new FormData();
formData.append("video", fileInput.files[0]);
formData.append("videoTitle", "Launch Demo");
formData.append("saveOriginalFile", "true");
formData.append("autoAudioEnhancement", "true");
formData.append("videoOptimization", "storage_saver");
formData.append("enableCaption", "true");
formData.append("engCaption", "true");
formData.append("hindiCaption", "true");
const response = await fetch("https://api.streamlet.in/api-key/start-video-processing", {
method: "POST",
headers: {
"x-streamlet-api-key": "sk_streamlet_live_xxxxxxxxxxxxxx",
"x-streamlet-account-number": "681b58c58d8c0a55b7c64b2c"
},
body: formData
});
const data = await response.json();
console.log(data);Queued upload response
JSON
{
"success": true,
"videoId": "Launch Demo-1775211037986",
"userId": "681b58c58d8c0a55b7c64b2c",
"status": "queued",
"message": "Video uploaded and queued for processing",
"statusUrl": "/video-processing-status/Launch%20Demo-1775211037986"
}Plan Limits
Streamlet enforces storage and video duration limits per plan. Uploads that exceed these caps are rejected before any processing begins — both from the dashboard and from the API.
Video duration limit
Free-plan accounts may only upload videos up to 6 minutes (360 seconds). Videos longer than this are rejected with HTTP 403 and the error code DURATION_LIMIT_EXCEEDED. Paid plans have no duration restriction.
| Plan | Max video duration | Storage | Max resolution | 2K output | 4K output | Caption quota / month | Watermark |
|---|---|---|---|---|---|---|---|
free | 6 minutes | 1 GB | 480p | No | No | 10 minutes | Forced — streamlet.in |
starter | Unlimited | 50 GB | 720p | No | No | 5 hours | Optional custom text |
builder | Unlimited | 200 GB | 2K (1440p) | enable2kOutput=true | No | 25 hours | Optional custom text |
pro | Unlimited | 500 GB | 4K (2160p) | enable2kOutput=true | enable4kOutput=true | 50 hours | Optional custom text |
Caption quota
Each plan includes a monthly caption quota based on the total duration of videos processed with captions enabled. The quota resets on the 1st of each month. Requests that would exceed the quota are rejected with HTTP 403 and the error code CAPTION_QUOTA_EXCEEDED.
Duration limit error (HTTP 403)
JSON
{
"success": false,
"error": "Video duration (420s) exceeds the 6-minute limit for the free plan. Upgrade to process longer videos.",
"code": "DURATION_LIMIT_EXCEEDED"
}Caption quota exceeded error (HTTP 403)
JSON
{
"success": false,
"error": "Caption quota exhausted for this month. Upgrade your plan or wait for the monthly reset.",
"code": "CAPTION_QUOTA_EXCEEDED"
}Watermark
Streamlet enforces watermark rules per plan:
- Free plan — every video is automatically stamped with a
streamlet.inwatermark. This cannot be disabled and theenableWatermark/watermarkTextfields are ignored. - Paid plans (Starter, Builder, Pro) — the watermark is fully optional. Pass
enableWatermark=truewith a customwatermarkText(max 60 characters) to overlay your own text, or omit / passenableWatermark=falseto encode with no watermark at all.
Upload with custom watermark (paid plans)
JavaScript
const formData = new FormData();
formData.append("video", fileInput.files[0]);
formData.append("videoTitle", "Launch Demo");
// Paid plan: add a custom watermark
formData.append("enableWatermark", "true");
formData.append("watermarkText", "© MyBrand 2024");
// Paid plan: disable watermark entirely — omit or set to "false"
// formData.append("enableWatermark", "false");
const response = await fetch("https://api.streamlet.in/api-key/start-video-processing", {
method: "POST",
headers: {
"x-streamlet-api-key": "sk_streamlet_live_xxxxxxxxxxxxxx",
"x-streamlet-account-number": "681b58c58d8c0a55b7c64b2c"
},
body: formData
});
const data = await response.json();
console.log(data);| Field | Type | Description |
|---|---|---|
enableWatermark | string — "true" / "false" | Paid plans only. Set to "true" to add a custom watermark, or "false" / omit to encode with no watermark. Ignored for free-plan accounts — streamlet.in is always applied. |
watermarkText | string (max 60 chars) | Custom text to overlay on the video. Only applied when enableWatermark=true on a paid plan. |
Upload Image
POST to /api-key/upload-image with a single image file. Streamlet auto-rotates, resizes to a max of 2000 px wide, converts to WebP at quality 85, and returns back you the processed image. The response includes a ready-to-use cdnUrl and the final pixel dimensions.
Accepted formats: JPEG, PNG, WebP, AVIF, GIF. Maximum upload size is 20 MB. Storage counts toward the account quota.
Upload an image
JavaScript
const formData = new FormData();
formData.append("image", fileInput.files[0]);
const response = await fetch("https://api.streamlet.in/api-key/upload-image", {
method: "POST",
headers: {
"x-streamlet-api-key": "sk_streamlet_live_xxxxxxxxxxxxxx",
"x-streamlet-account-number": "681b58c58d8c0a55b7c64b2c"
},
body: formData
});
const data = await response.json();
console.log(data.cdnUrl);
// "https://cdn.streamlet.in/681b.../images/product-banner-1775211037986.webp"Image upload response
JSON
{
"success": true,
"imageId": "product-banner-1775211037986",
"cdnUrl": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/images/product-banner-1775211037986.webp",
"streamletKey": "681b58c58d8c0a55b7c64b2c/images/product-banner-1775211037986.webp",
"width": 1200,
"height": 630,
"sizeBytes": 84320
}Upload Document
POST to /api-key/upload-document with a single PDF file. Streamlet stores the file and returns a permanent CDN URL instantly — no processing queue, no polling needed. Use the URL directly in your app, email, or embed it in a viewer.
Accepted format: PDF only. Maximum upload size is 50 MB. Storage counts toward the account quota.
Upload a PDF document
JavaScript
const formData = new FormData();
formData.append("document", fileInput.files[0]);
const response = await fetch("https://api.streamlet.in/api-key/upload-document", {
method: "POST",
headers: {
"x-streamlet-api-key": "sk_streamlet_live_xxxxxxxxxxxxxx",
"x-streamlet-account-number": "681b58c58d8c0a55b7c64b2c"
},
body: formData
});
const data = await response.json();
console.log(data.cdnUrl);
// "https://cdn.streamlet.in/681b.../documents/product-spec-1775211037986.pdf"Document upload response
JSON
{
"success": true,
"documentId": "product-spec-1775211037986",
"cdnUrl": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/documents/product-spec-1775211037986.pdf",
"streamletKey": "681b58c58d8c0a55b7c64b2c/documents/product-spec-1775211037986.pdf",
"originalFilename": "product-spec.pdf",
"sizeBytes": 245760
}Video Status
GET /api-key/video-processing-status/:videoId to fetch the current status for one video. Use the returned videoId from the upload response.
Get processing status
JavaScript
const response = await fetch(
"https://api.streamlet.in/api-key/video-processing-status/your_video_id",
{
headers: {
"x-streamlet-api-key": "sk_streamlet_live_xxxxxxxxxxxxxx",
"x-streamlet-account-number": "681b58c58d8c0a55b7c64b2c"
}
}
);
const data = await response.json();
console.log(data);Completed status response
JSON
{
"success": true,
"videoId": "Launch Demo-1775211037986",
"userId": "681b58c58d8c0a55b7c64b2c",
"videoTitle": "Launch Demo",
"title": "Launch Demo",
"visibility": "Private",
"fileName": "product-demo.mp4",
"fileSizeBytes": 6681892,
"fileMimeType": "video/mp4",
"status": "completed",
"queuedAt": "2026-04-03T10:10:39.888Z",
"keepOriginal": true,
"autoAudioEnhancement": true,
"generateCaptions": true,
"captionLanguages": ["english", "hindi"],
"originalVideoUrl": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/original/product-demo.mp4",
"streamUrl": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/master.m3u8",
"thumbnail": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/thumbnail.jpg",
"audioPlaylistUrl": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/vaudio/playlist.m3u8",
"durationSeconds": 27.814286,
"captions": {
"en": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/captions.en.vtt",
"hi": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/captions.hi.vtt"
},
"chapters": {
"vtt": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/chapters.vtt",
"json": "https://cdn.streamlet.in/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/chapters.json"
},
"completedAt": "2026-04-03T10:12:14.748Z"
}Health API
GET /health to verify service uptime and queue visibility. This is useful for infrastructure checks before sending upload traffic.
curl "https://api.streamlet.in/health"