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.
Start an upload
Section titled “Start an upload”/v1/uploads (scope write)
{ "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.
{ "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.
Upload the parts
Section titled “Upload the parts”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.
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;}Resume an interrupted upload
Section titled “Resume an interrupted upload”/v1/uploads/{id} lists the parts WireVoD already has and returns fresh URLs for the parts
that are still missing:
{ "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.
Complete the upload
Section titled “Complete the 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.
{ "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.
| Error | Status | What it means |
|---|---|---|
upload_incomplete | 400 | A part is missing |
part_size_mismatch | 400 | A part has an unexpected size; upload it again |
part_etag_mismatch | 400 | An etag you sent doesn’t match the stored part |
upload_not_pending | 409 | The upload was cancelled or has expired |
storage_integrity | 502 | The assembled file failed verification; start a new upload |
Cancel an upload
Section titled “Cancel an upload”/v1/uploads/{id} (scope write) discards the parts uploaded so far. Cancelling twice is
harmless; a completed upload can’t be cancelled.
Upload states
Section titled “Upload states”status | Meaning |
|---|---|
created | Accepting parts |
completed | Verified and handed to processing |
aborted | Cancelled |
expired | Not completed within 24 hours |