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.

TemplateStackPurpose
Next.js Video UploadNext.js 16Frontend starter for Streamlet SDK-based upload and processing flows.
Next.js Image UploadNext.js 16Frontend starter for image hosting and CDN delivery.
Next.js PlayerNext.js 16Playback-focused Streamlet player starter.
Node.js Express REST APINode.js / ExpressProxy Streamlet REST API routes from an Express backend.
Go REST APIGoStreamlet REST wrapper for Go services.
Python REST APIPython / FastAPIFastAPI example for Streamlet uploads and status endpoints.
Rust REST APIRust / AxumRust backend starter for Streamlet REST integrations.
Java REST APIJava / Spring BootSpring 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

Every video is transcoded into an adaptive HLS ladder with thumbnails and optional captions. There are two upload endpoints, and both take the same multipart form fields for processing options. The server responds immediately with a videoId — use the Status API to poll for completion.

  • Standard Stream POST /api-key/standard/start-video-processing. Public adaptive HLS with no access restrictions.
  • Protected Stream POST /api-key/protected/start-video-processing. Everything in Standard plus edge access control (country, domain, and IP rules enforced at the CDN edge). Requires the Builder, Pro, or Scale plan.

Pass enable2kOutput=true(Builder, Pro & Scale plans) to add a 1440p (2K) rendition to the HLS adaptive ladder. Pass enable4kOutput=true(Pro & Scale plans) to add a 2160p (4K) rendition. Both flags are silently ignored on plans that do not support them.

The legacy POST /api-key/start-video-processing endpoint (which reads a protectionMode body field) still works but is deprecated — use the two dedicated endpoints above for all new integrations.

Standard Stream

POST to /api-key/standard/start-video-processing with multipart form data. Upload the source video, set the title, and optionally enable captions and high-resolution output.

Create a standard stream

JavaScript

const formData = new FormData();
formData.append("video", fileInput.files[0]);
formData.append("videoTitle", "Launch Demo");
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.streamletedge.com/api-key/standard/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",
  "protectionMode": "standard",
  "message": "Video uploaded and queued for processing",
  "statusUrl": "/video-processing-status/Launch%20Demo-1775211037986"
}

Protected Stream

POST to /api-key/protected/start-video-processing with the same processing fields as Standard plusthe edge access rules below. All rule fields are optional, stored as arrays, and enforced at the CDN edge. You can also edit them later from each video's Security & access menu in the dashboard. This endpoint requires the Builder, Pro, or Scale plan.

FieldTypeDescription
publishedstring"true" / "false"Default "true". Set "false" to make the video unavailable to everyone.
allowedCountriesJSON array string2-letter ISO country codes, e.g. ["IN","US","AE"]. Empty = worldwide.
allowedDomainsJSON array stringDomains allowed to embed the player. Empty = any site.
allowedIPsJSON array stringViewer IPs allowed to play. Empty = any IP.
blockedIPsJSON array stringViewer IPs that are always denied.

Create a protected stream

JavaScript

const formData = new FormData();
formData.append("video", fileInput.files[0]);
formData.append("videoTitle", "Launch Demo");
formData.append("autoAudioEnhancement", "true");
formData.append("enableCaption", "true");
formData.append("engCaption", "true");

// Edge access rules (all optional)
formData.append("published", "true");
formData.append("allowedCountries", JSON.stringify(["IN", "US", "AE"]));
formData.append("allowedDomains", JSON.stringify(["app.mybrand.com"]));
formData.append("allowedIPs", JSON.stringify([]));
formData.append("blockedIPs", JSON.stringify(["203.0.113.7"]));

const response = await fetch("https://api.streamletedge.com/api-key/protected/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);

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 10 minutes (600 seconds). Videos longer than this are rejected with HTTP 403 and the error code DURATION_LIMIT_EXCEEDED. Paid plans have no duration restriction.

PlanMax video durationStorageMax resolution2K output4K outputCaption quota / monthWatermark
free10 minutes2 GB480pNoNo10 minutesForced — streamletedge.com
starterUnlimited100 GB1080pNoNo10 hoursOptional custom text
builderUnlimited400 GB2K (1440p)enable2kOutput=trueNo30 hoursOptional custom text
proUnlimited1 TB4K (2160p)enable2kOutput=trueenable4kOutput=true75 hoursOptional custom text
scaleUnlimited2 TB4K (2160p)enable2kOutput=trueenable4kOutput=true150 hoursOptional / white-label

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 (720s) exceeds the 10-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 streamletedge.com watermark. This cannot be disabled and the enableWatermark / watermarkText fields are ignored.
  • Paid plans (Starter, Builder, Pro) — the watermark is fully optional. Pass enableWatermark=true with a custom watermarkText (max 60 characters) to overlay your own text, or omit / pass enableWatermark=false to 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.streamletedge.com/api-key/standard/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);
FieldTypeDescription
enableWatermarkstring"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 — streamletedge.com is always applied.
watermarkTextstring (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.streamletedge.com/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.streamletedge.com/681b.../images/product-banner-1775211037986.webp"

Image upload response

JSON

{
  "success": true,
  "imageId": "product-banner-1775211037986",
  "cdnUrl": "https://cdn.streamletedge.com/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.streamletedge.com/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.streamletedge.com/681b.../documents/product-spec-1775211037986.pdf"

Document upload response

JSON

{
  "success": true,
  "documentId": "product-spec-1775211037986",
  "cdnUrl": "https://cdn.streamletedge.com/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.streamletedge.com/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",
  "protectionMode": "protected",
  "published": true,
  "allowedCountries": ["IN", "US", "AE"],
  "allowedDomains": [],
  "allowedIPs": [],
  "blockedIPs": [],
  "fileName": "product-demo.mp4",
  "fileSizeBytes": 6681892,
  "fileMimeType": "video/mp4",
  "status": "completed",
  "queuedAt": "2026-04-03T10:10:39.888Z",
  "autoAudioEnhancement": true,
  "generateCaptions": true,
  "captionLanguages": ["english", "hindi"],
  "streamUrl": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/master.m3u8",
  "thumbnail": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/thumbnail.jpg",
  "audioPlaylistUrl": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/vaudio/playlist.m3u8",
  "durationSeconds": 27.814286,
  "captions": {
    "en": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/captions.en.vtt",
    "hi": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/captions.hi.vtt"
  },
  "chapters": {
    "vtt": "https://cdn.streamletedge.com/681b58c58d8c0a55b7c64b2c/video/Launch%20Demo-1775211037986/processed/chapters.vtt",
    "json": "https://cdn.streamletedge.com/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.streamletedge.com/health"