Embed API

Securely embed Streamr in partner applications with authenticated users.

Use this reference when integrating Streamr into a partner application. For setup and a live preview, use Configure an Embed. For API-key creation (admins only), token generation and token validation, use Embed API Utilities.

HTTPS Required

Embed authentication uses cookies with sameSite=none to work in third-party iframe contexts. This requires HTTPS in production.

  • Both your app and the parent page must use HTTPS.
  • Session cookies will not work over HTTP in production.
  • For local testing, use tools like ngrok or configure local HTTPS.

Configure an Embed

Configure authentication, choose Creator, Agent, or Showcase mode, and preview your embed in a live iframe.

Configure an Embed

Overview

The Streamr Embed API authenticates users inside embedded iframes using JWT tokens. This provides a single sign-on style experience without forcing users through an OAuth flow inside the iframe.

There are two authentication paths:

  • API Key to Embed JWT: call /api/embed/generateToken with your API key and a user email to get a short-lived signed JWT, then pass it as ?token=.
  • Auth0 Access Token: if you already have an Auth0 access token for the user, pass it directly as ?token=. The embed validates it through Auth0 /userinfo and resolves the email automatically.

Embed Modes

The embed supports Creator, Agent and Showcase modes through the mode query parameter.

Creator Mode

Creator mode is the default. It opens the creative editor for generating and editing ad creatives.

/embed?token=TOKEN

Agent Mode

Agent mode opens the AI Chat agent with navigation between Chat, Creatives, and Campaigns. Create, edit, and save flows work normally within the iframe.

/embed?token=TOKEN&mode=agent

In agent mode, users can navigate between AI Chat, Creatives, and Campaigns using the tab bar. Save actions redirect within the iframe, and users can tab back to chat.

Showcase Mode

Showcase mode opens the delegated publisher workspace. It requires an Auth0 access token and authorized SpringServe publisher context; the URL does not grant account access.

/embed?token=AUTH0_ACCESS_TOKEN&mode=showcase&authContext=springserve/publisher/ACCOUNT_ID

Use Configure an Embed to choose an accessible publisher account. Existing downstream account and role checks still apply.

Appearance and Agent Options

ParameterApplies toBehavior
theme=light or theme=darkAll modesLocks the iframe theme without changing the user's saved preference. Omit to inherit the saved or system theme.
header=falseAgentHides the agent header.
agentAgentLocks the selected agent; use the configurator's available built-in or activated custom agents.
authContextAgent or ShowcaseSelected account context in platform/type/id format; existing access checks apply. Showcase requires springserve/publisher/<id>.
userAgentURL-encoded opening prompt. It is submitted once when the chat is ready; on brands requiring an account choice, the user selects the account and submits it manually.
/embed?token=TOKEN&mode=agent&theme=dark&user=Help%20me%20review%20a%20campaign

Integration Practices

Generate API-key tokens on your backend and keep API keys out of client code. Use the appropriate Auth0 tenant for staging or production. Choose short expiration times for sensitive operations and handle auth-expired messages to refresh the iframe. Include allow="geolocation" only when the integration needs high-accuracy place autocomplete; IP-based location remains the fallback.

API Reference

Generate Token

POST /api/embed/generateToken

Generate a signed JWT token for embed authentication.

Headers:

X-API-Key: your-api-key

Request body:

{
  "email": "user@example.com",
  "expiresIn": "24h"
}

Response:

{
  "success": true,
  "token": "eyJhbGc...",
  "embedUrl": "https://yourapp.com/embed?token=eyJhbGc...",
  "expiresIn": "24h"
}

Validate Token

POST /api/embed/validateToken

Validate a token and create a user session. This accepts both Streamr embed JWTs and Auth0 access tokens.

Request body:

{
  "token": "eyJhbGc..."
}

Response for a Streamr embed JWT:

{
  "success": true,
  "tokenValid": true,
  "user": {
    "email": "user@example.com",
    "organizationId": "org-123",
    "organizationName": "Acme Corp"
  }
}

Response for an Auth0 access token in cookie-free or Safari mode:

{
  "success": true,
  "tokenValid": true,
  "user": { "email": "user@example.com" },
  "sessionToken": "eyJhbGc..."
}

When third-party cookies are blocked, the embed uses cookie-free mode. For Auth0 tokens, /api/embed/validateToken issues a short-lived Streamr embed JWT in sessionToken so the middleware receives a locally verifiable token on later requests.

Embedding in Your App

For a Streamr embed JWT generated through the API key path:

<iframe
  src="https://your-instance.com/embed?token=YOUR_EMBED_JWT_HERE"
  width="100%"
  height="600"
  frameborder="0"
  allow="clipboard-write; geolocation"
></iframe>

For a direct Auth0 access token:

<iframe
  src="https://your-instance.com/embed?token=YOUR_AUTH0_ACCESS_TOKEN_HERE"
  width="100%"
  height="600"
  frameborder="0"
  allow="clipboard-write; geolocation"
></iframe>

The email is resolved from the Auth0 token automatically. Staging tokens validate against the staging Auth0 tenant; production tokens validate against production.

Loading a Saved Creative

To open the embed with a previously saved creative pre-loaded, add creativeId and createdAt query parameters.

<iframe
  src="https://your-instance.com/embed?token=YOUR_TOKEN_HERE&creativeId=cr_xxx&createdAt=2026-01-06T17%3A18%3A51.926Z"
  width="100%"
  height="600"
  frameborder="0"
  allow="clipboard-write; geolocation"
></iframe>

Parameters:

ParameterRequiredDescription
tokenYesStreamr embed JWT or Auth0 access token.
creativeIdNoCreative ID, such as cr_1767719931926_2tfqjs9.
createdAtNoURL-encoded ISO 8601 creation timestamp.

When both creativeId and createdAt are provided, the embed fetches the creative after authentication and loads its template, settings, and media into the player. Editing and saving creates a new creative; the original is not modified.

PostMessage Events

Creative Saved

When a user saves a creative in the embed, the parent window receives a message with the saved creative data.

window.addEventListener('message', (event) => {
  const message = event.data

  if (message.type === 'creative-saved') {
    const creativeId = message.creative.data.entityId.split('#')[2]
    const createdAt = message.creative.data.createdAt

    console.log('Creative ID:', creativeId)
    console.log('Created At:', createdAt)
  }
})

Message shape:

{
  "type": "creative-saved",
  "creative": {
    "success": true,
    "data": {
      "entityOwner": "PLAT#streamr#USER#user@example.com",
      "entityId": "CREATIVE#2026-01-06T17:18:51.926Z#cr_1767719931926_2tfqjs9",
      "createdAt": "2026-01-06T17:18:51.926Z",
      "updatedAt": "2026-01-06T17:18:51.926Z"
    }
  }
}

Re-Opening a Saved Creative

After capturing a creative-saved event, re-open that creative by including its ID and timestamp in the iframe URL.

window.addEventListener('message', (event) => {
  const message = event.data

  if (message.type === 'creative-saved') {
    const creativeId = message.creative.data.entityId.split('#')[2]
    const createdAt = message.creative.data.createdAt
    const token = 'YOUR_TOKEN_HERE'

    iframe.src = `https://your-instance.com/embed?token=${token}`
      + `&creativeId=${creativeId}`
      + `&createdAt=${encodeURIComponent(createdAt)}`
  }
})

Auth Expired

When a user's session or token expires inside creator or agent mode, the iframe posts an auth-expired message so the parent page can generate a fresh token and reload the iframe.

window.addEventListener('message', async (event) => {
  const message = event.data

  if (message.type === 'auth-expired') {
    const newToken = await fetchNewTokenFromYourBackend()
    iframe.src = `${location.origin}/embed?token=${newToken}`
  }
})

Message shape:

{
  "type": "auth-expired"
}

Embed Resize

Creator mode continuously monitors its content height and posts an embed-resize message when it changes. Use this to resize the iframe so it fits its content. This event is not emitted in agent mode; use a fixed height such as 800px.

window.addEventListener('message', (event) => {
  if (event.data.type === 'embed-resize' && typeof event.data.height === 'number') {
    iframe.style.height = event.data.height + 'px'
  }
})

Message shape:

{
  "type": "embed-resize",
  "height": 742
}

Always verify event.origin in production before processing messages.

API Calls After Embed Auth

After token validation, use the session cookie for API requests.

Get all templates:

const response = await fetch(`${baseUrl}/api/templates`, {
  headers: { Cookie: sessionCookie }
})
const { templates, defaultTemplateId } = await response.json()

Get a specific creative:

const response = await fetch(
  `${baseUrl}/api/creatives/${creativeId}?userEmail=${encodeURIComponent(userEmail)}&createdAt=${encodeURIComponent(createdAt)}`,
  {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      Cookie: sessionCookie
    }
  }
)
const creative = await response.json()

Start a video render:

const response = await fetch(`${baseUrl}/api/creatomate/render`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Cookie: sessionCookie
  },
  body: JSON.stringify({
    templateId: '82881724-b4df-48d6-ae49-51c7ee44640f',
    modifications: {
      'Text-1': 'Hello World',
      'Image-1': 'https://example.com/image.jpg'
    },
    pollUntilComplete: false
  })
})
const result = await response.json()

Check render status:

const response = await fetch(`${baseUrl}/api/creatomate/check-render?renderId=${renderId}`, {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    Cookie: sessionCookie
  }
})
const statusResult = await response.json()

Testing and MCP Integration

  • MCP Test Console (admin access required) to test initialization, tool discovery, tool calls, responses, and errors with your browser session.
  • Open AI Agent to test the chat interface that uses MCP under the hood.
  • For external agents, call POST /api/mcp and include the embed token in the x-api-key header.

Embed API Utilities

Embed API Utilities provides interactive token generation and validation, copyable request examples, and admin API-key creation. It also shows brand-specific broadcast download details when configured. These actions retain their existing login and API access requirements.