AITV embed template

Mint on the server → load the iframe → postMessage AITV_EMBED_INIT when the shell is ready.

Demo only — prod: server mint.

Additional configuration — layout, session TTL, refresh timing, embed UIExpand / collapse
How to integrate AITV embedExpand / collapse
  • Mint (server): POST https://api.aitv.gg/api/v0/embed/sessions with Authorization: Bearer sk_…. Body: channelRef (slug or UUID), origin (parent site, no path), optional ttlSeconds (60–86400; default 600). Same model as Producer → Settings → Embed API.
  • Iframe: https://aitv.gg/embed/<channelRef>. Optional ?layout=horizontal|vertical.
  • Hand off JWT: when the shell is ready, postMessage to https://aitv.gg with AITV_EMBED_INIT and sessionToken. Refresh by minting again before expiresAt and re-sending init (no iframe reload required).
  • Billing: audio-generating conversations use channel hours (rounded up to whole minutes).
HTML snippet
<iframe
  src="https://aitv.gg/embed/your-channel-slug-or-uuid"
  style="width: 100%; height: 720px; border: 0;"
  allow="camera; microphone; clipboard-read; clipboard-write; fullscreen; autoplay; encrypted-media"
></iframe>
<script>
  // Backend: POST /api/v0/embed/sessions with your embed API key — never expose sk_... here.
  const iframe = document.currentScript.previousElementSibling;
  iframe.addEventListener('load', () => {
    iframe.contentWindow.postMessage({
      type: 'AITV_EMBED_INIT',
      sessionToken: 'YOUR_SESSION_JWT_FROM_SERVER',
      options: {
        disableDefaultInput: false
      }
    }, 'https://aitv.gg');
  });
</script>
LLM / agent prompt
You are embedding an AITV channel agent on a website.

Goal:
- Embed the channel inside an iframe using https://aitv.gg/embed/your-channel-slug-or-uuid
- Never put the long-lived channel API key (sk_...) in the browser.

Layout:
- Default (recommended): omit the layout param (dynamic sizing, fills the iframe bounds)
- Horizontal (16:9): https://aitv.gg/embed/your-channel-slug-or-uuid?layout=horizontal
- Vertical (9:16): https://aitv.gg/embed/your-channel-slug-or-uuid?layout=vertical

Server (owner backend):
1. Store the channel embed API key (sk_...) only on the server.
2. Mint a short-lived embed session JWT:
   POST https://api.aitv.gg/api/v0/embed/sessions
   Authorization: Bearer sk_...
   Content-Type: application/json
   Body: { "channelRef": "your-channel-slug-or-uuid", "origin": "https://your-site.example", "ttlSeconds": 600 }
   (ttlSeconds optional: omit for default 600s, or send 60–86400 each time).
   Response: { "token": "...", "expiresAt": "ISO-8601", "ttlSeconds": 600, ... }
   The embed key authorizes minting only. `origin` is embedded in the JWT and must match the browser `Origin` when calling /api/v0/conversation.

Refreshing without interrupting the user:
- Before expiry (see expiresAt), call the mint endpoint again with the same channel and origin.
- Send the new sessionToken to the iframe (postMessage "AITV_EMBED_INIT"). Do not reload the iframe; only swap the bearer for /api/v0/conversation. Mint the next token early if you want overlap.

Browser:
- After the iframe loads, postMessage to https://aitv.gg:
  - type: "AITV_EMBED_INIT"
  - sessionToken: <token from mint response>
  - options: { disableDefaultInput?: boolean, showMinutesRemaining?: boolean }

Optional:
- To programmatically send a message, postMessage:
  - type: "AITV_EMBED_SEND"
  - text: "Hello"

Do not store sk_ in git. Keep it in a secret manager.

Optional env: EMBED_API_KEY, NEXT_PUBLIC_EMBED_CHANNEL_REF, API_URL_BASE, NEXT_PUBLIC_IFRAME_URL_BASE. Mint sends your page origin into the JWT.

https://aitv.gg

Mint a session to show the embed