LinkedIn Videos API: 4 MB parts, ETags and finalizeUpload

LinkedIn video upload is initializeUpload, PUT each 4 MB part, collect the ETags, then finalizeUpload. A part splitter and the order rules that break uploads.

4 min readSume
All posts

LinkedIn's Videos API uploads in four steps: call initializeUpload with the owner and fileSizeBytes, split the file into 4 MB parts, PUT each part to its upload URL and keep the ETag from every response, then call finalizeUpload with the video URN, the upload token and the ETags in the same order as the parts. The finalize step is order-sensitive, so keep the ETags in a list indexed by part. The splitter below gives you the byte ranges LinkedIn expects.

Rules on the page

LinkedIn Videos API, version 202609 view, read 2026-10-02
ItemWhat the page says
InitializePOST /rest/videos?action=initializeUpload; fileSizeBytes decides the part count
Part sizeFirst range 0-4194303, next 4194304-8388607, and so on
Part uploadHTTP PUT to each uploadUrl; save the ETag response header
FinalizePOST /rest/videos?action=finalizeUpload with video, uploadToken and uploadedPartIds
OrderuploadedPartIds must match the order in uploadInstructions
URL expiryTypically 30 days after initialize; an expired URL gives 401
HeadersLinkedin-Version and X-Restli-Protocol-Version: 2.0.0 on every call

A splitter that matches the ranges

Read the ranges from the uploadInstructions response rather than computing them, but the same arithmetic is useful for tests: every part is 4,194,304 bytes except the last.

PART = 4 * 1024 * 1024

def ranges(total):
    if total <= 0:
        raise ValueError("empty file")
    out, first = [], 0
    while first < total:
        last = min(first + PART, total) - 1
        out.append((first, last))
        first = last + 1
    return out

for a, b in ranges(10 * 1024 * 1024)[:3]:
    print(a, b)

Getting `fileSizeBytes`

The size must be exact. If the file came out of Sume, take the byte length from your own download of the file. For clips that need shortening before upload, video trim cuts a range for $0.02 per job.

Upload loop shape

Run the PUTs from the uploadInstructions array in order, send each byte range exactly as named (firstByte through lastByte, inclusive), and append the ETag header value to a list before moving on. If a part fails, retry that part, not the whole file. When every part has an ETag, finalize once. Because the upload URLs usually last 30 days, a resumed job can often continue, but an expired URL returns 401 and means you must initialize again. Poll the video by its URN until status is AVAILABLE; the page lists PROCESSING, PROCESSING_FAILED, AVAILABLE and WAITING_UPLOAD.

Limits

The page also lists a general size range of 75 KB to 500 MB, a length of 3 seconds to 30 minutes, and MP4 only, and elsewhere a 5 GB cap on fileSizeBytes; those two numbers disagree, which is covered in 500 MB versus 5 GB. Send MP4 and stay under 500 MB. Sume cannot see or store the ETags; they belong to your uploader.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume