Docs / Video

Videos & ingest

The entry point to the whole pipeline: create a video record, then get bytes in by whatever path fits — direct presigned upload, S3-style multipart, resumable TUS, or a server-side pull from a URL.

presignedmultipartresumable (TUS)pull-from-URL

Create a video

Everything starts here. Create the record, then choose an ingest path below — or pass source_url and skip uploading entirely.

POST /v1/videos videos:write

Create the vid_… record before any bytes exist. Returns a one-time upload_token (for resumable TUS). All fields are optional: playback_policy = signed (default) | public; quality_preset = low | standard | high | av1; max_height caps the ladder; encrypt:true turns on AES-128 HLS; access_rules gates by country/referrer.

curl
curl -X POST https://api.ollanode.com/v1/videos \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q3 All-Hands",
    "playback_policy": "signed",
    "quality_preset": "high",
    "max_height": 1080,
    "encrypt": true,
    "access_rules": { "allowed_countries": ["US","IN"] }
  }'
201 Created
{ "id": "vid_7Qk3...", "status": "created",
  "playback_policy": "signed", "encrypted": true,
  "quality_preset": "high", "max_height": 1080,
  "upload_token": "<shown once — TUS metadata>", "chapters": [],
  "created_at": "..." }
Use cases
  • Pre-register a video and hand the client an upload target.
  • Gate a video to specific countries at create time.
POST /v1/videos videos:write

Pull-from-URL: set source_url and the platform fetches the file itself (SSRF-vetted, size-capped) and starts processing — no separate upload step. Returns immediately; the fetch runs in the background.

curl
curl -X POST https://api.ollanode.com/v1/videos \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Imported clip","source_url":"https://cdn.example.com/master.mp4"}'
Use cases
  • One-call import of an existing remote MP4.
  • Migrate a back-catalogue by pointing at your current origin.

Lifecycle: list, get, update, delete

Standard tenant-scoped CRUD — every call is scoped to your project.

GET /v1/videos videos:read

List videos (paginated; filter with ?library_id=). Ready videos include a short-lived presigned poster_url.

curl
curl "https://api.ollanode.com/v1/videos?limit=20&offset=0" \
  -H "Authorization: Bearer $OLLANODE_API_KEY"
GET /v1/videos/{id} videos:read

Fetch a single video with its full metadata, chapters, and access rules.

PATCH /v1/videos/{id} videos:write

Update title, playback_policy, metadata, library_id (empty string detaches), or access_rules.

DELETE /v1/videos/{id} videos:delete

Soft-delete the video and async-purge its storage. Agent keys get 202 {approval_id} (approval-gated).

There is no reprocess endpoint. Stuck or lost jobs are recovered automatically by background redispatch/reaper loops; "re-process from errored" is a state-machine property, not a public route.

Poll status

GET /v1/videos/{id}/status videos:read

Cheap poll: current lifecycle state (created → upload_pending → uploaded → processing → ready | errored) plus live transcode progress (0–100). Poll this after upload instead of the full GET.

curl
curl https://api.ollanode.com/v1/videos/vid_7Qk3.../status \
  -H "Authorization: Bearer $OLLANODE_API_KEY"
Response
{ "id":"vid_7Qk3...", "status":"processing", "error_reason":null, "progress":63 }

Ingest A — direct presigned upload

Best for small/medium files: mint a presigned PUT, upload the whole file straight to object storage, then finalize. Bytes never pass through the API.

curl
# 1) mint a presigned PUT URL
curl -X POST https://api.ollanode.com/v1/videos/vid_7Qk3.../upload-url \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content_type":"video/mp4"}'
# -> { "url":"https://...presigned PUT...", "source_key":"...", "expires_in":3600 }

# 2) upload the whole file to that URL
curl -X PUT --upload-file ./movie.mp4 -H "Content-Type: video/mp4" "<url>"

# 3) finalize -> starts the pipeline
curl -X POST https://api.ollanode.com/v1/videos/vid_7Qk3.../upload-complete \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" -d '{"size_bytes":52428800}'

Ingest B — multipart (large files)

S3-style multipart for large or chunked uploads: begin → presign each part → complete. The complete call finalizes the object and starts the pipeline itself.

curl
# 1) begin
curl -X POST https://api.ollanode.com/v1/videos/vid_7Qk3.../multipart \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" -d '{"content_type":"video/mp4"}'
# -> { "upload_id":"...", "source_key":"..." }

# 2) presign + PUT each part (capture the ETag from each response)
curl -X POST https://api.ollanode.com/v1/videos/vid_7Qk3.../multipart/<upload_id>/parts/1 \
  -H "Authorization: Bearer $OLLANODE_API_KEY"
# -> { "url":"https://...presigned PUT for part 1..." }

# 3) complete -> starts the pipeline (no upload-complete needed)
curl -X POST https://api.ollanode.com/v1/videos/vid_7Qk3.../multipart/<upload_id>/complete \
  -H "Authorization: Bearer $OLLANODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"parts":[{"part_number":1,"etag":"<etag-1>"},{"part_number":2,"etag":"<etag-2>"}]}'

Ingest C — resumable (TUS)

For browser uploads that must survive flaky networks or page reloads, use the TUS protocol against tusd at /files/ (not a gateway route). Send TUS metadata videoId=<vid_…> and uploadToken=<token from create>. tusd stores the object and calls a secret-gated completion hook that binds the upload to the video via that one-time token — a wrong or absent uploadToken is silently ignored, which is what keeps uploads tenant-isolated.

Use any TUS client (e.g. tus-js-client) pointed at https://<your-host>/files/. Next: Processing & AI covers what happens after the bytes land.