Chunkify Uploader

Setup

Configure upload sessions, completion, drag-and-drop, and file size limits.

Pass an upload session to the upload JavaScript property or React prop. The session comes from the Uploads API and contains these fields:

import type { UploadSession } from '@chunkify/uploader';

// Returned by your backend for each selected file.
type Session = UploadSession;
// { upload_url: string, completion_url: string }

Create a session when a file is selected

Use an async provider to create a fresh session for each upload. The component passes the selected File to the provider. /your-api/create-upload-session is a placeholder for a route you implement and authenticate in your application. That route calls the Chunkify API using your project token and returns the upload session. Replace this path with your own backend route.

async function createUpload(file) {
    const response = await fetch('/your-api/create-upload-session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ filename: file.name }),
    });
    if (!response.ok) throw new Error('Could not create an upload session.');
    return response.json();
}

For HTML, assign the provider as a JavaScript property. Objects and functions cannot be passed as HTML attributes.

<chunkify-uploader drop>
    <chunkify-uploader-file-select>Select a file</chunkify-uploader-file-select>
    <chunkify-uploader-progress-text></chunkify-uploader-progress-text>
    <chunkify-uploader-progress-bar></chunkify-uploader-progress-bar>
    <chunkify-uploader-error>Upload failed. Please try again.</chunkify-uploader-error>
    <chunkify-uploader-retry>Retry</chunkify-uploader-retry>
    <chunkify-uploader-success>Upload complete!</chunkify-uploader-success>
</chunkify-uploader>
document.querySelector('chunkify-uploader').upload = createUpload;

In React, use the same provider:

<ChunkifyUploader upload={createUpload} drop>
    <ChunkifyUploaderFileSelect>Select a file</ChunkifyUploaderFileSelect>
    <ChunkifyUploaderProgressText />
    <ChunkifyUploaderProgressBar />
    <ChunkifyUploaderError>Upload failed. Please try again.</ChunkifyUploaderError>
    <ChunkifyUploaderRetry>Retry</ChunkifyUploaderRetry>
    <ChunkifyUploaderSuccess>Upload complete!</ChunkifyUploaderSuccess>
</ChunkifyUploader>

Import these components from @chunkify/uploader/react.

Return the session from your backend

Your backend calls Chunkify with a project token. Keep that token on the server. The browser receives only the session fields it needs to upload and complete that one file.

This Express handler uses the project's default storage. Mount it after your application's authentication and authorization middleware. It must authorize the current user to upload to the selected project and storage.

app.post('/your-api/create-upload-session', async (req, res) => {
    try {
        const response = await fetch('https://api.chunkify.dev/v1/api/uploads', {
            method: 'POST',
            headers: {
                Authorization: `Bearer ${process.env.CHUNKIFY_PROJECT_TOKEN}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({}),
        });
        if (!response.ok) {
            return res.status(502).json({ error: 'Could not create an upload session.' });
        }
        const { data } = await response.json();
        const { upload_url, completion_url } = data;
        res.set('Cache-Control', 'no-store');
        return res.json({ upload_url, completion_url });
    } catch {
        return res.status(502).json({ error: 'Could not create an upload session.' });
    }
});

The provider sends filename to your backend for applications that need it. It is not an Uploads API field. Choose and validate the destination on your backend before building the request to Chunkify.

To override the project's default, replace the empty request body with a storage ID. For Chunkify-managed storage, omit path:

body: JSON.stringify({ storage_id: 'YOUR_CHUNKIFY_STORAGE_ID' })

Customer-connected storage requires an object path including the filename. This also applies when the project's default is customer-connected storage:

body: JSON.stringify({
    storage_id: 'YOUR_CONNECTED_STORAGE_ID',
    path: 'sources/video.mp4',
})

Allocate an appropriate path for each file. Do not blindly trust the browser's filename or storage ID. The component does not choose storage or request credentials from the end user.

Sessions expire after two hours by default. Your backend can set expires_in between 300 and 36000 seconds. See the upload guide for the full API flow.

Provide an existing session

You can assign a session that your backend has already created:

uploader.upload = session;
<ChunkifyUploader upload={session}>...</ChunkifyUploader>

Each session is for one file. After an attempt, replace it before the next selection. The component rejects a session it has already used. An async provider handles this naturally and is usually easier to integrate.

Completion and retries

The component sends the file to upload_url using PUT, then sends an empty POST to completion_url. It uses the returned URL as-is, without a project token or cookies on the completion request.

The progress percentage measures the file transfer. It stays at 100% while completion runs. The component emits upload-success only after completion returns 204.

For network failures, HTTP 429, or server errors, completion gets up to three attempts. The component waits between attempts. An expired completion URL returns HTTP 410, which is not retried. It does not send the file again during these retries. Each completion request has a 30-second timeout. The component does not impose a time limit on the file transfer.

HTTP 403 and other client errors are not automatically retried. The component displays the error content supplied by your application. The upload-error event includes technical details for your application. Configuration, storage permissions, and account issues must be resolved by the application owner.

The Retry control resets the component to file selection. The next selection requests a fresh session. It does not manually retry completion. If a completion response was lost, the previous upload may already have completed; use webhooks or a backend status read to reconcile it.

Browser CORS configuration

The browser contacts your backend, the storage bucket, and the completion API. If your backend is on another origin, configure its CORS rules for your frontend.

For customer-connected storage, allow browser PUT requests and the Content-Type header from the origin of the page hosting the uploader, such as https://app.example.com. If you also upload through the Chunkify dashboard, add https://chunkify.dev to the bucket's allowed origins. Chunkify also needs permission to read the uploaded object to create the Source.

Chunkify handles CORS for its completion endpoint. Your bucket's CORS rules are separate. See storage CORS configuration for provider examples.

Drag and drop and file size limits

Set drop to enable dropping files anywhere on the component. Use max-file-size in HTML or maxFileSize in React to limit the file size in MB. Omit it or use zero for no component-side limit. Chunkify's plan limits still apply.

<chunkify-uploader drop max-file-size="1024">...</chunkify-uploader>
<ChunkifyUploader upload={createUpload} drop maxFileSize={1024}>...</ChunkifyUploader>