Skip to main content
Upload large files in multiple chunks. This endpoint is designed for uploading files that are too large to send in a single request, or for implementing resumable uploads.

Endpoint

POST /api/upload/partial

Authentication

Requires authentication via Bearer token in the Authorization header.
Authorization: Bearer <your-token>

How It Works

  1. Send the first chunk with Content-Range starting at byte 0
  2. Server responds with a partialIdentifier
  3. Send subsequent chunks with the same partialIdentifier
  4. Mark the last chunk with X-Zipline-P-Lastchunk: true
  5. Server processes the complete file asynchronously

Request

Multipart Form Data

Send one file chunk as multipart/form-data. Only one file field is allowed per request.

Headers

Content-Range
string
required
Byte range of the current chunk in format: bytes START-END/TOTAL.
Content-Range: bytes 0-999999/5000000
The first chunk must start at byte 0.
X-Zipline-P-Filename
string
required
Original filename with extension.
X-Zipline-P-Filename: large-video.mp4
X-Zipline-P-Content-Type
string
required
MIME type of the complete file.
X-Zipline-P-Content-Type: video/mp4
X-Zipline-P-Content-Length
string
required
Total size of the complete file in bytes.
X-Zipline-P-Content-Length: 5000000
X-Zipline-P-Identifier
string
Partial upload identifier (provided by server after first chunk). Required for all chunks except the first.
X-Zipline-P-Identifier: a8b9c0d1
X-Zipline-P-Lastchunk
boolean
default:"false"
Set to true for the final chunk to trigger file processing.
X-Zipline-P-Lastchunk: true

Additional Headers

All standard upload headers from /api/upload are supported and should be sent with the first chunk:
  • X-Zipline-Format
  • X-Zipline-Filename (override generated name)
  • X-Zipline-File-Extension
  • X-Zipline-Domain
  • X-Zipline-Deletes-At
  • X-Zipline-Password
  • X-Zipline-Max-Views
  • X-Zipline-Original-Name
  • X-Zipline-Folder
Image compression headers are not supported for partial uploads.

Response

Chunk Acknowledgement (all chunks except last)

files
array
required
Empty array until the last chunk.
partialSuccess
boolean
required
Always true for successful chunk upload.
partialIdentifier
string
Unique identifier for this upload session (returned on first chunk only).

Final Response (last chunk)

files
array
required
Array containing the uploaded file object.
files[].id
string
required
Unique file identifier.
files[].name
string
required
Generated filename with extension.
files[].type
string
required
MIME type of the file.
files[].url
string
required
Full URL to access the file.
files[].pending
boolean
Set to true - file is being processed asynchronously.
partialSuccess
boolean
required
Always true for successful upload.
deletesAt
string
ISO 8601 timestamp when file will be deleted, or "never" if no expiration.

Examples

First Chunk (1MB file in 2 chunks)

curl -X POST https://your-zipline.com/api/upload/partial \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Range: bytes 0-524287/1048576" \
  -H "X-Zipline-P-Filename: video.mp4" \
  -H "X-Zipline-P-Content-Type: video/mp4" \
  -H "X-Zipline-P-Content-Length: 1048576" \
  -H "X-Zipline-Format: uuid" \
  -H "X-Zipline-Deletes-At: 30d" \
  -F "file=@/tmp/chunk1.bin"
Response:
{
  "files": [],
  "partialSuccess": true,
  "partialIdentifier": "a8b9c0d1"
}

Second Chunk (middle chunk)

curl -X POST https://your-zipline.com/api/upload/partial \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Range: bytes 524288-786431/1048576" \
  -H "X-Zipline-P-Filename: video.mp4" \
  -H "X-Zipline-P-Content-Type: video/mp4" \
  -H "X-Zipline-P-Content-Length: 1048576" \
  -H "X-Zipline-P-Identifier: a8b9c0d1" \
  -F "file=@/tmp/chunk2.bin"
Response:
{
  "files": [],
  "partialSuccess": true
}

Final Chunk

curl -X POST https://your-zipline.com/api/upload/partial \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Range: bytes 786432-1048575/1048576" \
  -H "X-Zipline-P-Filename: video.mp4" \
  -H "X-Zipline-P-Content-Type: video/mp4" \
  -H "X-Zipline-P-Content-Length: 1048576" \
  -H "X-Zipline-P-Identifier: a8b9c0d1" \
  -H "X-Zipline-P-Lastchunk: true" \
  -F "file=@/tmp/chunk3.bin"
Response:
{
  "files": [
    {
      "id": "clx7g8kj30001abc123xyz",
      "name": "550e8400-e29b-41d4-a716-446655440000.mp4",
      "type": "video/mp4",
      "url": "https://files.example.com/550e8400-e29b-41d4-a716-446655440000.mp4",
      "pending": true
    }
  ],
  "partialSuccess": true,
  "deletesAt": "2024-12-31T23:59:59.000Z"
}

Server-Side Processing

When the last chunk is received:
  1. File metadata is created in the database
  2. Background worker combines all chunks
  3. File is uploaded to configured datasource
  4. Database is updated with final file size
  5. Webhooks are triggered (if configured)
The file URL is immediately available, but the file may not be accessible until processing completes (indicated by pending: true).

Error Responses

400 Bad Request

  • Missing required partial headers
  • Invalid Content-Range format
  • Invalid or missing partialIdentifier (after first chunk)
  • Multiple files in one request (only one allowed)
  • Disabled file extension
  • Invalid filename characters

403 Forbidden

  • Folder not open for uploads

413 Payload Too Large

  • Total file size exceeds maxFileSize limit
  • Upload would exceed user quota

Notes

The server caches partial upload state in memory. If the server restarts, you’ll need to start the upload from the beginning.
Temporary chunk files are stored in the server’s configured tempDirectory with a prefix like zipline_partial_{identifier}_.
You must send chunks sequentially. The server validates that chunks are received in order.
File processing happens asynchronously after the last chunk. The file URL is returned immediately but may not be accessible for a few seconds.

Build docs developers (and LLMs) love