Skip to content
Docs
Get early access

Uploading videos

Resumable, direct uploads for lessons of any length.

Uploads go directly to secure storage in parts. Your server or app sends bytes straight to WireVoD’s storage with short-lived upload URLs, so large files upload quickly and an interrupted upload resumes where it stopped. Files can be up to 100 GiB.

/v1/uploads (scope write)

Request body
{ "asset_id": "6f1c2a9e-…", "size_bytes": 2147483648 }

You can also send sha256 (64 lowercase hex characters) for an end-to-end integrity check. The asset must be pending or failed, and an asset can have only one active upload at a time.

Response · 201
{
"upload": {
"id": "a41e7c03-…",
"asset_id": "6f1c2a9e-…",
"part_size": 16777216,
"part_count": 128,
"size_bytes": 2147483648,
"expires_at": 1760367600000,
"parts": [{ "number": 1, "url": "https://…" }]
}
}

WireVoD chooses part_size. Part n (counting from 1) covers bytes [(n − 1) × part_size, n × part_size); the last part holds the remainder.

Send each part’s bytes with PUT to its url. The URL itself is the credential, so don’t add authentication headers. Keep each response’s ETag header if you want WireVoD to cross-check it.

  • Upload URLs are valid for one hour.
  • Parts can go in parallel and in any order; three or four at a time works well.
  • Retry a failed part with the same URL while it’s valid.
upload.js
async function uploadParts(file, upload) {
const parts = [];
for (const part of upload.parts) {
const start = (part.number - 1) * upload.part_size;
const body = file.slice(start, Math.min(start + upload.part_size, file.size));
const res = await fetch(part.url, { method: "PUT", body });
if (!res.ok) throw new Error(`Part ${part.number} failed (${res.status})`);
parts.push({ number: part.number, etag: res.headers.get("etag") });
}
return parts;
}

/v1/uploads/{id} lists the parts WireVoD already has and returns fresh URLs for the parts that are still missing:

Response · 200
{
"upload": {
"id": "a41e7c03-…",
"status": "created",
"uploaded_parts": [{ "number": 1, "size": 16777216, "etag": "\"9b1f…\"" }],
"missing_part_urls": [{ "number": 2, "url": "https://…" }]
}
}

Upload the missing parts, then complete. An upload session lasts 24 hours; after that it expires and the asset can take a new upload.

/v1/uploads/{id}/complete (scope write). The body is optional because WireVoD verifies every part itself; if you include parts, each etag is checked as well.

Request body
{ "parts": [{ "number": 1, "etag": "\"9b1f…\"" }] }

On success the asset moves to uploaded and processing begins. Completing an upload twice returns the same result, so it’s safe to retry.

ErrorStatusWhat it means
upload_incomplete400A part is missing
part_size_mismatch400A part has an unexpected size; upload it again
part_etag_mismatch400An etag you sent doesn’t match the stored part
upload_not_pending409The upload was cancelled or has expired
storage_integrity502The assembled file failed verification; start a new upload

/v1/uploads/{id} (scope write) discards the parts uploaded so far. Cancelling twice is harmless; a completed upload can’t be cancelled.

statusMeaning
createdAccepting parts
completedVerified and handed to processing
abortedCancelled
expiredNot completed within 24 hours