Embed

Create short-lived tokens for customer-facing widgets.

Embed tokens let a browser show one customer's handoff brief without exposing your API key. Mint a short-lived token on your backend, then pass it to the frontend.

What a token authorizes

A token is bound to your organization, your key's agent, and the one customer you named when minting it. It works only on the public /embed/handoff endpoints:

EndpointToken scopePurpose
GET /embed/handoff?token=…handoff:read or handoff:writeFetch the customer's handoff brief, plus embedScope
POST /embed/handoff/resolvehandoff:writeMark the open issue resolved
POST /embed/handoff/reviewhandoff:writeMark the open issue reviewed
POST /embed/handoff/reopenhandoff:writeReopen a resolved issue
POST /embed/handoff/snoozehandoff:writeSnooze the open issue until a date
PATCH /embed/handoff/issuehandoff:writeSet the issue's priority or tags
POST /embed/handoff/noteshandoff:writeAdd an internal agent note

Tokens cannot read memories, list customers, capture turns, or reach any other customer. The embed endpoints are rate-limited to 60 requests per minute per IP.

Create a token

The default mode is view, which mints a read-only handoff:read token. Pass "mode": "agent" to mint a handoff:write token for an interactive panel. TTL is 60–86,400 seconds (default 3,600).

const { token, expiresIn, scope } = await client.createEmbedToken(
  { customerId: 'f3b39d1b-2522-4a00-98df-8cdde783ba12' },
  { ttlSeconds: 900 },
)

The SDK methods mint read-only (view) tokens. To mint a write-capable token, call the endpoint directly with "mode": "agent".

Use the token

Hosted agent panel — the simplest option. Embed ConvoMem's agent panel in an iframe; it renders the brief and, with a handoff:write token, the triage actions:

panel.html
<iframe
  src="https://app.convomem.com/embed/agent-panel?token=EMBED_TOKEN"
  width="420" height="640" frameborder="0"
  title="ConvoMem Agent Handoff"></iframe>

Your own UI — call the embed endpoints from the browser. No API key is involved:

frontend.ts
// Your backend minted the token with POST /embed/tokens
const res = await fetch(
  `https://api.convomem.com/api/v1/embed/handoff?token=${encodeURIComponent(token)}`,
)
const brief = await res.json()
// brief.narrative, brief.openIssue, brief.embedScope ('handoff:read' | 'handoff:write')
 
// With a handoff:write token: add a note to the open issue
await fetch('https://api.convomem.com/api/v1/embed/handoff/notes', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token,
    conversationId: '87c53d10-85f8-4447-920f-b1e847c23a1a',
    body: 'Customer confirmed the refund arrived.',
  }),
})

Write actions take the token in the JSON body (or the token query parameter) and a conversationId that must be a UUID. A read-only token returns 401 on write actions.

Response fields

FieldTypeDescription
tokenstringThe embed token to use in client-side code
expiresInnumberTime until expiration in seconds
scopestringhandoff:read or handoff:write

Token lifecycle

  1. Mint — Your backend calls /embed/tokens with a customer identity
  2. Pass — Return the token to your frontend
  3. Use — The panel or your UI sends the token to the /embed/handoff endpoints
  4. Expire — After ttlSeconds, the token returns 401; mint a new one

What's next

  • Handoff — server-side briefing that doesn't need a browser token
  • Authentication — API key vs embed token security model

SDK: TypeScript · Python · Rust