Path parameters
ParameterDescription
uploadUrl
string
requiredThe uploadUrl from Create Upload, used exactly as returned.
Header parameters
ParameterDescription
Content-Length
integer
requiredThe size of the body in bytes. HTTP clients set it when the body is a file or a buffer.
Content-Range
string
optionalOnly when sending in pieces: bytes {first}-{last}/{size}, for example bytes 52428800-104857599/120000000. A piece starts at a multiple of chunkSize and is chunkSize bytes long, except the last. Leave it out when the whole file is one piece.
Content-MD5
string
optionalThe piece's MD5, base64-encoded. AWS S3 and Azure Blob check it; SharePoint and Google Drive refuse it.
Request body
ParameterDescription
(body)
binary
requiredThe raw bytes of the file or the piece. Not a form and not base64.

Example request

# The second 50 MB piece of a 120,000,000-byte file, saved as piece2.bin
curl --request PUT "$UPLOAD_URL" \
  --header 'Content-Range: bytes 52428800-104857599/120000000' \
  --data-binary @piece2.bin

Response body

StatusWhen
202 AcceptedThe piece is stored; nextExpectedRanges lists what is still missing. An empty list means the file is being put together: GET the upload URL after a few seconds.
201 CreatedThis piece finished the upload. The answer carries file.
200 OKThe upload was already finished, for example when you resend the last piece after its answer was lost. Same file as the 201.

A 201 or 200 looks like this. file.id works with every file endpoint, and file.fullName is the stored name.

{
  "id": "upl_66f3c1a2b4d5e6f708192a3b",
  "status": "completed",
  "library": "s3",
  "driveId": "workspace",
  "name": "Q3-report.pdf",
  "size": 120000000,
  "chunkSize": 52428800,
  "chunkCount": 3,
  "maxConcurrency": 4,
  "bytesReceived": 120000000,
  "nextExpectedRanges": [],
  "expiresAt": "2026-09-25T11:05:09.000Z",
  "fileId": "66f3c1b9b4d5e6f708192a40",
  "file": {
    "id": "66f3c1b9b4d5e6f708192a40",
    "name": "Q3-report",
    "fullName": "Q3-report.pdf",
    "type": "file",
    "extension": "pdf",
    "source": "INTERNAL",
    "size": 120000000,
    "createdAt": "2026-09-25T10:05:12.000Z",
    "updatedAt": "2026-09-25T10:05:12.000Z",
    "createdBy": "Priya Shah",
    "driveId": "workspace",
    "library": "s3",
    "parent": {
      "id": "66f3c1a2b4d5e6f708192a32",
      "type": "folder",
      "driveId": "workspace"
    },
    "path": "Contracts/2026/Q3-report.pdf"
  }
}

Errors

StatuserrorCodeWhat it means
400UPLOAD/INVALID_RANGEContent-Range or the body's length does not match the upload. message says how.
404UPLOAD/NOT_FOUNDNo upload at this URL.
409UPLOAD/OUT_OF_ORDERSharePoint and Google Drive take pieces in order. GET the upload URL and send the first missing piece.
409UPLOAD/NOT_ACCEPTING_CHUNKSThe upload was cancelled or ended by an error. Create a new one.
410UPLOAD/EXPIREDThe upload expired. Create a new one.
411UPLOAD/LENGTH_REQUIREDThe request had no Content-Length.
429UPLOAD/CHUNKS_IN_FLIGHTToo many pieces at once. Send it again after Retry-After seconds.
503UPLOAD/STORAGE_UNAVAILABLEThe storage was busy. Send it again after Retry-After seconds.

Upload Errors lists every code and what to do.