Upload a video through the API and put it on a page
You have a video file and want it playing on your own web page. The job is a handful of API calls: ask for an upload address, send the file to it, wait until the video is ready, and paste the embed code the API returns. You never write the player markup yourself.
POST /videos/upload with the exact file size and visibility PUBLIC answers with data.video.id and data.upload.url. Send the file to that address with curl -L -X PUT --data-binary, read GET /videos/:id/status until status is READY, then paste responsive from GET /videos/:id/embed. Run the calls on your server with a pk_ key; the key never goes into browser code.Steps in order
- Check the room:
GET /quotareturnsdata.availablein bytes. A file that does not fit is refused in the next step with403 QUOTA_EXCEEDED. - Create the upload:
POST /videos/uploadwithtitle,fileName,fileSize(the exact size of the file in bytes) andvisibility. Keepdata.video.idanddata.upload.url; the address works for one hour (data.upload.expiresAt). - Send the file:
PUTthe bytes todata.upload.url. The address answers307and the body must be sent again to the new address;curl -L, fetch and axios do this. A file larger thandata.upload.chunkSizegoes in parts with aContent-Rangeheader. A finished upload answerscomplete: true. - Wait for the video: read
GET /videos/:id/statusevery 10 to 30 seconds untilstatusisREADY(orFAILED). To skip the polling, subscribe to thevideo.processing.completedwebhook: see Know when a video is ready. - Allow your website if your account limits embedding: read
embedAllowlistfromGET /me, add your domain and send the whole list toPATCH /me/embed-allowlist. An empty list means every website may show the video. - Get the embed code:
GET /videos/:id/embedreturnsresponsiveandiframe. Pasteresponsiveinto your page as returned.
The calls
| Call | Auth | What you get |
|---|---|---|
GET /quota | key | available and limit in bytes, usedPercent and isExceeded. |
POST /videos/upload | key | data.video (id, status, visibility), data.upload (url, expiresAt, chunked, chunkSize, maxFileSize) and data.statusUrl. |
PUT /uploads/:token | signed address | Takes the bytes of the file. Answers 307 to the place that stores the file, then videoId, fileSize, status (UPLOADED) and complete. |
POST /uploads/:token/tus | signed address | A resumable upload on the same address (headers Tus-Resumable: 1.0.0 and Upload-Length): answers 201 with a Location to continue at. For large files and unreliable connections. |
GET /videos/:id/status | key | status (PENDING, UPLOADING, PROCESSING, READY or FAILED), progress and stages. |
PATCH /videos/:id | key | Changes title, description or visibility, for example to PUBLIC after an upload that started private. |
GET /me | key | embedAllowlist, the websites that may show your player, with plan. |
PATCH /me/embed-allowlist | key | The new list as embedAllowlist. It replaces the whole list. |
GET /videos/:id/embed | key | responsive, iframe, url, width, height, aspectRatio and options. |
Example with curl
# 1. Is there room? → data.available (bytes)
curl -s -H "Authorization: Bearer pk_YOUR_KEY_HERE" "https://api.dcast.pro/api/v1/quota"
# 2. Create the upload → data.video.id, data.upload.url
# fileSize is the exact size of the file: stat -c %s video.mp4
curl -s -X POST "https://api.dcast.pro/api/v1/videos/upload" -H "Authorization: Bearer pk_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"title":"VIDEO_TITLE","fileName":"video.mp4","fileSize":17998762,"visibility":"PUBLIC"}'
# 3. Send the file to data.upload.url (no key; -L follows the 307 and re-sends the body)
curl -sS -L -X PUT --data-binary @video.mp4 -H "Content-Type: video/mp4" "UPLOAD_URL"
# → data.status "UPLOADED", data.complete true
# 4. Wait until data.status is READY
curl -s -H "Authorization: Bearer pk_YOUR_KEY_HERE" "https://api.dcast.pro/api/v1/videos/VIDEO_ID/status"
# 5. The player code → data.responsive, data.iframe, data.url
curl -s -H "Authorization: Bearer pk_YOUR_KEY_HERE" "https://api.dcast.pro/api/v1/videos/VIDEO_ID/embed"Who can watch the page
POST /videos/upload makes the video PRIVATE when you send no visibility, and a private video plays only for its owner. For a public page send PUBLIC in step 2, or change it afterwards with PATCH /videos/:id. LINK_ONLY lets anyone who has the link watch, without listing the video. All the values, and paid access, are described in Videos API.
Putting the player on the page
- Paste
responsiveexactly as returned: it fills the width of its container in the shape of the video. For a smaller player put it into a narrower container (for examplemax-width: 480px) and do not set a height, a border or a corner radius on the iframe. - The player starts by itself, muted, once it has loaded (
options.autoplayandoptions.mutedsay so). Keep one player on a page: for a list of videos show posters and load the player of the video a visitor clicks.
Uploads from a visitor's browser
Never put the key into a page. Your server makes the call of step 2 and hands only data.upload.url to the browser, and the browser sends the file to that address. DcastStudio.upload() from the DCAST script does the resumable upload for a page, and data-dcast-upload puts a ready upload button on it with no server at all. Both are described in Upload videos.
Limits
The plan sets how much storage you have and the highest quality kept for an uploaded video. A start that does not fit answers 403 QUOTA_EXCEEDED before any byte is sent. The numbers of the Free plan are on Free live streaming and video API, and every plan is on pricing.
A refused call answers with error.code and error.message. The codes are listed in Errors & limits.
For AI agents
Connect the DCAST MCP server at https://api.dcast.pro/mcp. Each tool is one API operation, and dcast_get_recipe returns the exact tool-call sequence for a job.
Recipe: upload-a-video-to-vod. The tools run in this order: get_storage_quota, create_video_upload (send visibility PUBLIC for a public page), the file itself with curl -L -X PUT --data-binary @FILE UPLOAD_URL from a terminal where the file is, get_video_status every 10 to 30 seconds until READY, then get_video_embed_code.
The file does not go through the connector. If you cannot reach the file, put the upload button (data-dcast-upload) on the page, or ask for a public link and call import_video_from_url. Paste responsive exactly as returned; never write an iframe by hand.
Never ask the person to create, copy or paste an API key. If the website's own server must call DCAST, call ask_site_access: the person clicks one Allow link and the key goes straight into the site's environment. You never see it.
