TUS upload API endpoint
How it works
- Create a video object using the Create Video API to get a
videoId. - Generate a presigned signature on your server using SHA256.
- Upload the file from the client using a TUS client library with the presigned credentials.
Authentication
To authenticate a TUS upload request, the following headers must be included:Video metadata parameters
The following metadata can be passed with the TUS upload:Generating the signature
The authorization signature is generated by hashing the concatenation of several values using SHA256:A 401 Unauthorized from the TUS endpoint means the
AuthorizationSignature doesn’t match the headers the request sends, or the VideoId, AuthorizationSignature, or AuthorizationExpire header is missing. The values your server signs must match the headers the client sends byte-for-byte: library ID, API key, expiration, and video ID.A 400 Bad Request means AuthorizationExpire is already in the past, or LibraryId is missing or invalid. The response body says which.Examples
Each framework guide signs the upload, sends the file, and plays the video once it’s encoded.Laravel
Rails
Django
Next.js
Nuxt
SvelteKit
Uppy with React
Basic client-side upload
Next.js App Router
This example shows a complete implementation using Next.js with the App Router.React with Express backend
Express server (server.js):
BUNNY_STREAM_API_KEY, BUNNY_STREAM_LIBRARY_ID, and APP_ORIGIN, the origin your React app runs on, such as http://localhost:5173. CORS only stops other websites from calling the API in a visitor’s browser. It doesn’t stop scripts, so the route still needs its own auth check.
Resuming uploads
One of the key benefits of TUS is the ability to resume interrupted uploads. Within a page session,tus-js-client retries failed requests and carries on from the last acknowledged chunk.
To resume after a reload, upload into the same video again. A stored upload URL belongs to one video, so resuming it with another video’s credentials sends the bytes to the old video and leaves the new one empty. Save the video ID against the file, ask your server to re-sign that video instead of creating a new one, and only resume when the IDs match:
Error handling
Implement proper error handling to provide a good user experience:Ensure any
AuthorizationExpire timestamp is at least 1 hour (3600 seconds) or longer to make sure uploads are completed before authorization expires.Resumable (TUS) upload FAQ
Common questions about how authorization and resumability behave when uploading video with the TUS resumable protocol.Can I re-sign an existing video GUID to resume an in-progress upload instead of creating a new video object?
Can I re-sign an existing video GUID to resume an in-progress upload instead of creating a new video object?
Yes. The same video GUID can be re-signed and used to resume through the existing TUS upload URL - there is no need to create a new video object.Note that a newly generated signature does not extend the upload resource’s original expiry. Re-signing lets you continue an existing upload; it does not reset the clock on how long that upload remains available.
How long does an incomplete TUS upload stay resumable, and what's returned once it expires?
How long does an incomplete TUS upload stay resumable, and what's returned once it expires?
An incomplete upload remains resumable until the
AuthorizationExpire value that was used when it was created, or after roughly 48 hours of inactivity - whichever comes first.Once it expires, requesting the upload returns 404 Not Found (not 410).