For the complete documentation index, see llms.txt. This page is also available as Markdown.

Embed Clarity

Render Clarity in a browser without exposing your API key.

The Clarity iframe is the fastest way to add a working card and chat to a browser app. You build no UI, and your API key never reaches the client.

The flow:

  1. Your backend mints a short-lived embed token.

  2. Your browser app receives only the iframe URL (the token is in its query string) and renders an <iframe>.

  3. The iframe loads from clarity-embed.motifapp.ai, fetches the card, and streams chat directly against Motif using the token.

  4. Your parent page optionally listens for postMessage events for resize and chat lifecycle.


Step 1: Mint a token (server-side)

const embed = await motif.clarity.createEmbed({
  portfolioId: 'ppf_abc',
  allowedOrigins: ['https://app.acme.com'],
  ttlSeconds: 900,
  scope: ['card', 'chat'],
})

return { iframeUrl: embed.url } // hand to the browser
curl -X POST https://api.motifapp.ai/api/v1/sdk/clarity/embeds \
  -H "x-api-key: $MOTIF_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "portfolioId": "ppf_abc",
    "allowedOrigins": ["https://app.acme.com"],
    "ttlSeconds": 900,
    "scope": ["card", "chat"]
  }'

Returns:

{
  "url": "https://clarity-embed.motifapp.ai/?token=eyJ...",
  "token": "eyJ...",
  "expiresAt": "2026-05-22T16:45:00Z",
  "jti": "..."
}

Hand the url to the browser. Mint a fresh token on each page load. The call is cheap.

  • ttlSeconds defaults to 900s (15 min). Max 3600s, min 30s.

  • scope defaults to ["card", "chat"]. Restrict to ["card"] to omit chat.

Token bindings

The token is bound to the portfolio you reference at mint time:

  • Pass portfolioId, and the iframe is locked to that portfolio. A different portfolioId or inline payload in a later call fails with 403.

  • Pass portfolio inline, and the token is hash-bound to that exact payload, which must be re-supplied on each request.

This binding is what makes the iframe safe to expose. A stolen token can only query the portfolio it was minted for, and only from the origins it was minted for.


Step 2: Render the iframe

The embed auto-fetches the card on mount and renders the Market context and Your positions sections plus an Ask Clarity chat input (omitted if you minted with scope: ["card"]). For a fully branded experience, build the UI yourself with the SDK and an embed token against the card and chat endpoints.


Step 3: Listen for parent-window events (optional)

The iframe posts window.postMessage events to its parent. Every message has source: 'motif-clarity-embed'.

resize fires whenever content height changes. Use it to keep the iframe sized to its content without inner scrollbars.


Allowed origins

allowedOrigins is enforced server-side on every Clarity call from the iframe. Motif reads the browser-sent Origin header, compares it against the list bound to the token, returns 403 if it doesn't match, and mirrors the matched origin back in Access-Control-Allow-Origin. You don't have to add Motif to any cross-origin allowlist. The iframe handles its own CORS.


Production checklist


Troubleshooting

Symptom
Likely cause

"Missing token query parameter"

The ?token=... is missing from the iframe URL.

401 "Invalid embed token"

The token expired, or was signed for a different environment.

403 "Origin not allowed for this token"

The hosting page isn't in allowedOrigins.

403 "Embed token missing card/chat scope"

The token was minted with a restricted scope.

403 "portfolioId does not match embed token binding"

The token is bound to a different portfolio than the request references.

Last updated