Source Upload

Video Upload

Create video sources from hosted URLs, connected storage, or files uploaded from disk.

Uploading a source

Before transcoding, create a source using one of these inputs:

  • An HTTP or HTTPS URL where the video is stored.
  • An object in connected external storage.
  • A file uploaded from disk.

Once Chunkify has analyzed the source, you can use its ID to create a transcoding job.

Upload from an URL

To create a source video from an URL you only need to create a new source using the adress of your video.

import Chunkify from '@chunkify/chunkify';

const client = new Chunkify({
    projectAccessToken: 'My Project Access Token',
});

// Create a source from a hosted file
const source = await client.sources.create({
    url: 'https://my-bucket.s3.us-east-1.amazonaws.com/media/file.mp4',
});

Use connected storage

The dashboard’s From storage option creates a Source that references the existing file. The file stays in its original bucket, so no Upload entry is created. Keep that object available while Chunkify processes it. The upload destination selector applies only when uploading a file from disk.

To read an existing object from connected AWS S3 or S3-compatible storage, create a source with a storage object. Run these examples on your server, where the project access token stays private. Replace the storage ID and object path with your own values.

import Chunkify from '@chunkify/chunkify';

const client = new Chunkify({
    projectAccessToken: 'My Project Access Token',
});

// Create a source from a file already in connected storage
const source = await client.sources.create({
    storage: {
        id: 'stor_aws_example',
        path: 'sources/video.mp4',
    },
});

storage.path is required. It is the exact object key in the bucket; Chunkify does not add the storage connection's output base_prefix.

Omit storage.id to use the project's external default storage:

{
  "storage": {
    "path": "sources/video.mp4"
  }
}

If no default storage is configured, or the default is Chunkify-managed storage, provide an external storage.id or use a root-level url. Provide either url or storage, never both.

The selected storage must belong to the project and allow reads of the object.

Chunkify saves the resolved storage ID on the source. Changing the project default later does not change where existing sources are read from.

See the storage guide for permissions and object lifetime requirements.

Upload from disk

A file upload has three steps:

  1. Your server creates a session with POST /api/uploads using a project access token.
  2. The client sends the file with PUT to the returned upload_url and checks for a successful response.
  3. The client sends an empty POST to the returned completion_url. HTTP 204 confirms that Chunkify verified the object and created its source.

The completion URL includes authorization for this upload only. Send no project access token or cookies to it.

Keep both URLs private; they are returned only when creating the upload and are absent from later reads, lists, and webhook payloads. Use upload_url as supplied. For completion, POST to completion_url directly or pass its token to the SDK's completion method.

Both requests must finish before expires_at. The default validity_timeout is 7200 seconds (2 hours); you can choose from 300 seconds (5 minutes) to 36000 seconds (10 hours). An expired session requires a new upload, even if the file transfer already finished.

Choose where the file goes

Omit storage.id to use the project's default storage, or provide the ID of another storage connection in the same project.

Where you want to upload Request body Object path
Chunkify storage, when it is already the project default {} Generated by Chunkify
Chunkify storage, when external storage is the project default {"storage":{"id":"stor_chunkify_id"}} Generated by Chunkify
External storage that is already the project default {"storage":{"path":"incoming/video.mp4"}} Exact supplied key
External storage that is not the project default {"storage":{"id":"stor_aws_example","path":"incoming/video.mp4"}} Exact supplied key

Replace the example storage IDs with the IDs from your project. Providing storage.id chooses the destination for this upload without changing the project's default storage.

External storage always requires storage.path, including the filename. The path is the exact bucket key, between 1 and 1024 UTF-8 bytes; the output base_prefix is not added. Uploading to an existing key can overwrite it.

Chunkify storage rejects a supplied path. Changing the project default later does not move an existing upload.

The connection must permit PutObject, HeadObject, and GetObject. Browser uploads also require bucket CORS that permits PUT from your application's origin and the headers your client sends.

Permission to call the completion endpoint does not configure bucket CORS.

Uploaded files in Chunkify storage are temporary and eligible for deletion after 24 hours. For external storage, you control cleanup and must keep the object available while Chunkify processes it.

You can attach metadata to the upload; Chunkify copies it to the created source. See metadata.

For customer-connected storage, configure bucket CORS at your provider before uploading from a browser. Chunkify does not apply these settings automatically. Allow https://chunkify.dev for dashboard uploads and your website's origin for uploads from your own frontend. Allow both if you use both. Follow the browser upload CORS setup for the required rules and a CLI example. A dashboard upload cannot verify CORS for your website's origin.

If your application uses a restrictive CSP, allow https://api.chunkify.dev and your storage endpoint in connect-src.

Transfer and complete the upload

These examples use the project's default storage. Add storage.id and storage.path to the session creation request when needed, as described above. Run them on your server, where the project access token remains private.

The SDK's completion method takes the token from the last path segment of completion_url. Pass that token unchanged after the file transfer succeeds. Completion returns no response body.

import fs from 'fs';
import Chunkify from '@chunkify/chunkify';

const client = new Chunkify({
    projectAccessToken: process.env.CHUNKIFY_PROJECT_TOKEN,
});

const upload = await client.uploads.create({});

// Upload your file using streaming
if (!upload.upload_url || !upload.completion_url) throw new Error('Missing upload session URLs');
const fileStream = fs.createReadStream('river_city.mp4');
const response = await fetch(upload.upload_url, {
    method: 'PUT',
    body: fileStream as any,
    duplex: 'half',
    headers: {
        'Content-Type': 'video/mp4',
    },
} as RequestInit & { duplex: 'half' });
if (!response.ok) throw new Error(`File transfer failed: ${response.status}`);

const token = new URL(upload.completion_url).pathname.split('/').pop()!;
await client.uploads.complete(token);

Retry completion safely

If the completion response is lost, times out, or returns 429 or 5xx, retry the same completion URL with a short, increasing delay before expires_at. Do not upload the file again.

A completed session returns 204 again without creating another source or billing twice.

An invalid token (401), rejected file, request, or terminal upload state (400), forbidden storage access (403), or expired session (410) needs attention instead of automatic retries.

Read the error response; an expired or failed upload requires a new session.

Use webhooks to continue your workflow

Instead of manually checking upload status and source creation, set up webhooks to get notified when uploads complete.

Configure a webhook to handle the upload.completed event, then automatically trigger transcoding jobs using the source ID from the notification payload. See the webhooks section to learn how to configure and use webhooks.