Getting started
Havik Player plays Oddin's live esports streams — low-latency HLS with DRM — in any modern browser. You can integrate it three ways:
| Mode | Best for | You provide | The SDK owns |
|---|---|---|---|
| Iframe embed | Fastest drop-in, CMS pages, no build step | an iframe slot | everything, behind a postMessage API |
| Managed player | Full control of look & behavior in your app | a <video> element | hls.js, LL-HLS tuning, DRM/EME, retries, controls |
| Bring your own player | Existing player stacks (hls.js, Shaka, wrapper) | the player + <video> | auth → catalog → playback resolution + DRM helpers |
Whichever mode you pick, you need the same two things:
- a match URN — identifies the stream, e.g.
od:match:1234 - a publishable api-key —
pk_live_…/pk_test_…, safe to ship in browser JavaScript because it only works from allow-listed origins
1. Get a key and a match
Onboarding is handled by Oddin: email havik-support@oddin.gg to get an api-key scoped to the tournaments you serve. Match URNs come from your odds-feed integration or from the SDK's catalog helpers.
2. Get your origins allow-listed
The api-key is publishable — its only guardrail is a server-side origin allow-list. Until your origins are onboarded, every request fails its CORS preflight and nothing plays. Send havik-support the exact origins you serve from, for both of:
- the key's AllowedOrigins — every origin the player runs on (and AllowedIframeParents for iframe embeds: the parent page's origin)
- the DRM service's CORS allow-list — same origins, or the license request dies in preflight and you get silent black video
Never ship a wildcard
A ["*"] allow-list disables the only guardrail on a publishable key. Don't ask for one in production.
Allow a few minutes for propagation. Include http://localhost:5173 (or your dev port) if you want local development to work.
3. Point at the right environment
baseUrl selects the Havik environment. Don't hard-code it deeper than a config value — serve it from your backend and keep the backend current from the endpoint directory:
| Environment | API baseUrl | Hosted embed page |
|---|---|---|
| Integration (this site) | https://feed-dev.oddin-video.gg | https://player-dev.oddin-video.gg/embed/ |
| Production | published in the endpoint directory | announced at onboarding |
Test keys (pk_test_…) work against integration; production keys against production. A key on the wrong environment fails with UNAUTHORIZED.
Live service health for every Havik component is published at status-dev.oddin-video.gg (integration) and status.oddin-video.gg (production).
4. Install
For the iframe embed there is nothing to install. For the SDK modes:
npm install @oddin-gg/havik-player<!-- Exposes window.HavikPlayer. Pin an exact version in production. -->
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@1/dist/havik-player.global.js"></script>TypeScript definitions ship with the package — the types are the source of truth for the API surface.
5. First playback
import { createPlayer } from '@oddin-gg/havik-player';
const player = await createPlayer({
video: document.querySelector('video')!,
baseUrl: 'https://feed-dev.oddin-video.gg',
matchUrn: 'od:match:1234',
credential: { apiKey: 'pk_test_…' },
autoplay: true,
muted: true, // required for reliable autoplay under browser sound policies
waitForLive: true, // arm on an upcoming match, auto-play at go-live
});
player.on('statechange', (s) => console.log('state:', s));
player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));If the match hasn't started, waitForLive arms the player and it attaches the moment the stream goes live — see the managed player guide.
Browser support
Chrome, Firefox, and Edge play via hls.js + Widevine. Safari and iOS play via hls.js (ManagedMediaSource) or native HLS with FairPlay. Use detectDrmSupport() to check a browser before rendering the player — see the DRM guide.
Next steps
- Embed the hosted player — the 5-minute integration
- Managed player — options, events, live pickup
- Controls & theming — make it look like your product
- Troubleshooting — the usual suspects, fast