Draft: these docs describe OctaVideo as it will be at launch; some features may not be live yet.
OctaVideoDocs

Secure playback

Request a one-time password (OTP) from your server for each viewer, then embed the player with it.

For paid or private videos, your server requests a fresh OTP for every signed-in viewer on every page view, and your page embeds the player with it.

How it works

One OTP per viewer per page view. Your private key never leaves your server.
  1. A signed-in viewer opens a page on your site that shows a video.
  2. Your server checks that this viewer may watch the video, then calls POST /playback/otp with the library's private key.
  3. OctaVideo returns an OTP and an embed_url that already contains it.
  4. Your page renders an iframe with that embed_url.
  5. The player redeems the OTP, checks the page's domain and the viewer's country against the library's security settings, and starts playback.

An OTP can be used once. Once the player redeems it, the viewer keeps watching, seeking and changing quality in that playback session without a new OTP.

Request an OTP

POST https://api.octavideo.tech/api/v1/playback/otp
AccessKey: ovk_your_private_key
Content-Type: application/json

Prop

Type

A successful request returns 201 Created:

201 Created
{
  "data": {
    "otp": "Zx8kQ2mVb7nR4tY1uW9eA3sD6fG0hJ5kL2pO8iU7yT4",
    "expires_at": "2026-10-25T09:35:00Z",
    "embed_url": "https://player.octavideo.tech/embed/0b8e5d3a-1c2f-4e6a-8b7d-9f0a1b2c3d4e/6f1c2b9e-4a7d-4f3e-9b8a-2d5c7e1f0a34?otp=Zx8kQ2mVb7nR4tY1uW9eA3sD6fG0hJ5kL2pO8iU7yT4"
  }
}
  • otp is 43 characters long and works once.
  • expires_at is when the OTP expires if nobody uses it, in UTC.
  • embed_url is the player URL to load in the iframe. Use it as is.

Always pass user_id

OctaVideo counts unique viewers by user_id. With it, one person counts once across their phone, laptop and tablet. Without it, each browser counts as a separate viewer, so the same student on two devices counts twice.

  • Send the viewer's ID from your own system, such as student-4821. Prefer an internal ID to an email address.
  • It is up to 128 printable ASCII characters, with no spaces.
  • Send the same user_id for the same person every time.

Embed the player

Request the OTP on your server right before you render the page, then put embed_url in the iframe. Each example reads the key from the OCTAVIDEO_KEY environment variable and escapes the URL before writing it into HTML:

curl -X POST "https://api.octavideo.tech/api/v1/playback/otp" \
  -H "AccessKey: $OCTAVIDEO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_id": "6f1c2b9e-4a7d-4f3e-9b8a-2d5c7e1f0a34", "user_id": "student-4821", "ttl_seconds": 300}'

# Then, in your page:
# <iframe src="EMBED_URL" style="border:0;width:100%;aspect-ratio:16/9"
#   allow="encrypted-media; fullscreen" allowfullscreen></iframe>

The iframe takes the width of its container and keeps a 16:9 ratio, so your page decides the size.

Best practices

  • One OTP per page view. Request a new OTP every time the page renders. Never cache an OTP, share it between viewers or reuse it after a reload.
  • Request it right before rendering. The default ttl_seconds of 300 gives the browser 5 minutes to load the player. Raise it only for pages that stay open a long time before the video loads.
  • Check access first. OctaVideo trusts your server: request an OTP only after you have checked that the viewer may watch this video.
  • Keep the key on the server. The browser only ever sees embed_url. See Authentication.

Errors

When you request the OTP:

StatusCodeMeaning
400validation_failedA field is missing or invalid; details.fields names it.
401unauthorizedThe AccessKey header is missing or the key is invalid.
404not_foundThe video doesn't exist in this library.
409video_not_readyThe video is still processing or failed. Wait until it is Ready.

When the player loads, it refuses to play and shows an error if:

CodeMeaningFix
unauthorizedThe OTP was already used or has expired.Request a new OTP for each page view.
domain_not_allowedThe page that embeds the player isn't on the library's allowed domains.Add the domain in Allowed domains.
country_blockedThe library blocks playback from the viewer's country.Review country blocking.

See Errors for the error format and the full list of codes.

What's next

On this page