Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Large File Uploads (TUS)

Upload files of any size using the TUS resumable upload protocol. TUS allows you to resume interrupted uploads and track progress.

Why TUS?

  • Resume interrupted uploads - Pick up from where you left off
  • No size limit - Upload files of any size
  • Progress tracking - Built-in offset tracking
  • Better for unreliable connections - Mobile, slow networks

Learn More

Visit tus.io for the official TUS protocol specification, implementation guides, and best practices.

Official TUS Clients

Use the official TUS client libraries for reliable uploads:

LanguageLibraryRepository
JavaScripttus-js-clientgithub.com/tus/tus-js-client
Gotus-go-clientgithub.com/tus/tus-go-client
Pythontuspygithub.com/tus/tuspy
Javatus-java-clientgithub.com/tus/tus-java-client

Using Our SDK

The Pinner SDK includes built-in TUS support:

pnpm add @lumeweb/pinner
import { Pinner } from "@lumeweb/pinner";
 
const pinner = new Pinner({ jwt: "YOUR_API_TOKEN" });
 
// Upload large file with automatic TUS
const operation = await pinner.upload.largeFile("large-file.zip");
const result = await operation.result;
 
console.log("CID:", result.cid);

Using Our CLI

The CLI handles TUS automatically for large files:

pinner upload large-file.zip --wait

TUS Server Capabilities

Query the TUS server for supported versions, extensions, and limits:

OPTIONS https://ipfs.pinner.xyz/api/upload/tus

Response Headers

HeaderDescription
Tus-VersionSupported protocol versions
Tus-ExtensionSupported extensions
Tus-Max-SizeMaximum upload size in bytes
Tus-Checksum-AlgorithmSupported checksum algorithms

Example

curl -X OPTIONS "https://ipfs.pinner.xyz/api/upload/tus" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

TUS Protocol Overview

If implementing TUS manually, the protocol follows these steps:

  1. Create upload - POST to /api/upload/tus with metadata
  2. Upload chunks - PATCH requests with file data and offset
  3. Finish upload - DELETE request
  4. Get CID - Poll /api/operations/{id}

Create Upload

POST https://ipfs.pinner.xyz/api/upload/tus
Headers:
  • Authorization: Bearer TOKEN
  • Tus-Resumable: 1.0.0
  • Upload-Length: <file-size-in-bytes>
  • Upload-Metadata: archive_mode <base64>,name <base64>
Status Codes:
  • 201 Created - Upload created (includes Location header)
  • 400 Bad Request - Checksum algorithm not supported
  • 412 Precondition Failed - TUS version mismatch
  • 413 Request Entity Too Large - Exceeds max size
  • 415 Unsupported Media Type - Wrong Content-Type

Upload Chunks

PATCH https://ipfs.pinner.xyz/api/upload/tus/{id}
Headers:
  • Authorization: Bearer TOKEN
  • Tus-Resumable: 1.0.0
  • Upload-Offset: <byte-offset>
  • Content-Type: application/offset+octet-stream
Status Codes:
  • 204 No Content - Chunk accepted (includes new Upload-Offset)
  • 400 Bad Request - Checksum algorithm not supported
  • 403 Forbidden - Cannot modify final upload
  • 404 Not Found - Upload resource not found
  • 409 Conflict - Offset mismatch
  • 410 Gone - Upload expired
  • 412 Precondition Failed - TUS version mismatch
  • 415 Unsupported Media Type - Wrong Content-Type
  • 460 Checksum mismatch

Finish Upload

DELETE https://ipfs.pinner.xyz/api/upload/tus/{id}
Status Codes:
  • 204 No Content - Upload terminated
  • 412 Precondition Failed - TUS version mismatch

Get Offset (HEAD)

HEAD https://ipfs.pinner.xyz/api/upload/tus/{id}
Status Codes:
  • 200 OK - Returns current offset (includes Upload-Offset header)
  • 403 Forbidden - Resource not accessible
  • 404 Not Found - Resource not found
  • 410 Gone - Upload expired
  • 412 Precondition Failed - TUS version mismatch

Get CID

GET https://ipfs.pinner.xyz/api/operations/{id}
Status Codes:
  • 200 OK - Returns operation status and CID when complete

See Also