API Documentation
Everything you need to integrate ContentHosting into your platform. Authenticate, upload, and embed videos via our REST API.
Authentication
The API supports two authentication methods:
1. API Key — pass your key in the X-API-Key header. This works for all /api/* endpoints.
2. Session Cookie — sign in via /auth/signin and use the returned ch_session cookie for subsequent requests. This is used by the web dashboard.
curl -H "X-API-Key: YOUR_KEY" \ https://contenthosting.org/api/videos
Sign Up
/auth/signupCreate a new user account and start a session.
| Field | Type | Description |
|---|---|---|
email | string | Valid email address |
password | string | Minimum 8 characters, max 128 |
// Response 201
{ "ok": true, "userId": "uuid-here" }
Sign In
/auth/signinAuthenticate and receive a session cookie.
| Field | Type | Description |
|---|---|---|
email | string | Registered email address |
password | string | Account password |
// Response 200
{ "ok": true, "userId": "uuid-here" }
Sign Out
/auth/signoutDestroy the current session. Requires a valid session cookie.
// Response 200
{ "ok": true }
Current User
/auth/meGet profile data for the authenticated user. Requires session cookie.
// Response 200
{ "user": { "id": "...", "email": "...", "createdAt": 1712... } }
Upload Presign
/api/upload/presignGet a presigned URL to upload a video file directly to cloud storage. Requires API key or session.
| Field | Type | Description |
|---|---|---|
fileName | string | Original file name |
mimeType | string | e.g. video/mp4 |
fileSize | number | File size in bytes |
title | string? | Optional video title |
description | string? | Optional description |
// Response 200
{
"objectKey": "videos/owner/...",
"presignedUrl": "https://...",
"expiresInSeconds": 900
}
Upload Complete
/api/upload/completeFinalize a video upload after the file has been PUT to the presigned URL.
| Field | Type | Description |
|---|---|---|
objectKey | string | The key from presign response |
title | string | Video title (1-200 chars) |
fileSize | number | File size in bytes |
mimeType | string | File MIME type |
description | string? | Optional description |
duration | number? | Duration in seconds |
// Response 201
{
"ok": true,
"videoId": "uuid",
"status": "ready",
"defaultPlayer": "jwplayer",
"embedUrl": "https://.../player/jwplayer?video=uuid",
"embeds": { "jwplayer": "<iframe ...>", ... }
}
List Videos
/api/videosRetrieve all videos owned by the authenticated user or API key.
// Response 200
{ "videos": [ { "id": "...", "title": "...", "status": "ready", ... } ] }
Get Embed Code
/api/embed/:videoIdGet embed markup and iframe URLs for all supported player types. No auth required.
// Response 200
{
"defaultPlayer": "jwplayer",
"embedUrl": "https://.../player/jwplayer?video=id",
"embeds": {
"jwplayer": "<iframe ...>",
"plyr": "<iframe ...>",
"videojs": "<iframe ...>",
"fluidplayer": "<iframe ...>"
}
}
Stream Media
/media/:videoIdDirect video stream with byte-range support. Returns the video file with proper Content-Type and Accept-Ranges headers. No auth required.
Player Types
ContentHosting supports four self-hosted, iframe-isolated video players:
| Player | URL Path | Notes |
|---|---|---|
| JW Player | /player/jwplayer?video=ID | Default player; feature-rich |
| Plyr | /player/plyr?video=ID | Lightweight, accessible |
| Video.js | /player/videojs?video=ID | Extensible, plugin ecosystem |
| Fluid Player | /player/fluidplayer?video=ID | Fill-to-container playback |