developerUpdated 2026-05-19

Embed API

What this covers

The Embed API lets third-party applications embed Tessallite's conversational agent or query capabilities inside their own products. Instead of requiring users to log in to Tessallite directly, the host application requests a scoped, time-limited token from its backend, then passes it to the embedded component. The end user never sees Tessallite credentials.

How embedding works

  1. The ISV backend authenticates to Tessallite as a tenant admin and calls POST /api/v1/auth/embed-token.
  2. Tessallite returns a signed JWT with restricted scope (tenant, persona, models, capabilities, expiry).
  3. The ISV backend passes the token to the browser (in page props, a cookie, or via a server-rendered attribute).
  4. The browser-side embed component (iframe or React component) uses the token for all Tessallite API calls.
  5. When the token nears expiry, the component fires a callback; the ISV backend requests a fresh token.

No Tessallite login page is shown. The end user's identity comes from the user_identity field in the token request, which appears in Tessallite's audit log.

Requesting an embed token

Endpoint: POST /api/v1/auth/embed-token

Authentication: Requires a tenant admin or system admin JWT (via cookie or Bearer header).

FieldTypeRequiredDefaultDescription
tenant_idstringyes-Target tenant slug
user_identitystringyes-Display name for audit trail
persona_idstringnonullLock to this persona's permissions
model_idsstring[]nonullRestrict visible models
capabilitiesstring[]noallAllowed features: query, chat, explore
expiry_minutesintegerno180Token lifetime (min 5, max 1440)

Scope fields

persona_id locks the session to a specific persona. All row-level security filters and measure/dimension access rules for that persona apply. If omitted, the embedded user sees the default (unfiltered) view.

model_ids restricts which models the token can access. Any query or chat request targeting a model not in the list returns 403. If omitted, all models in the tenant are accessible.

capabilities controls which features the embed can use:

If a capability is excluded, API calls to the corresponding service return 403.

Token lifetime

The default token lifetime is 3 hours (180 minutes), long enough for demos and presentations without interruption. The maximum is 24 hours (1440 minutes). The minimum is 5 minutes.

For production embedding, set the expiry shorter (30-60 minutes) and implement token refresh via the onTokenExpiring callback in the embed component.

Revoking a token early

A token normally stays valid until it expires. If a token leaks, or you simply want to cut a session short before its expiry, you can revoke it:

Endpoint: DELETE /api/v1/auth/embed-token/{jti}

The {jti} is the token's unique ID — the jti claim inside the signed JWT you minted. Only a tenant admin may revoke. Once revoked, the token stops working within about a minute (the platform refreshes its revocation list roughly once a minute), and every query or chat call made with it returns 403. The revocation is recorded in the Audit Log as embed_token.revoked. The platform cleans up the revocation record automatically once the token would have expired anyway (at most 24 hours, the maximum token lifetime), so the blocklist never grows without bound.

Revocation fails safe: if the platform cannot confirm a token is still valid, it refuses the request rather than letting it through. Build a revoke call into your "sign out" or "rotate credentials" flow so a leaked link can be cut off immediately rather than waiting out its expiry.

CORS configuration

Embedded components load from the ISV's domain. Set the ALLOWED_EMBED_ORIGINS environment variable (comma-separated):

ALLOWED_EMBED_ORIGINS=https://app.customer.com,https://portal.customer.com

This is merged with the standard CORS_ORIGINS setting. Both model-service and agent-service read it.

Example: Python

import requests

TESSALLITE_URL = "http://localhost:3000"

# 1. Log in as tenant admin
login = requests.post(f"{TESSALLITE_URL}/api/v1/auth/login", json={
    "tenant_id": "acme-demo",
    "email": "admin@acme-demo.com",
    "password": "acme-demo",
})
cookies = login.cookies

# 2. Request an embed token
resp = requests.post(
    f"{TESSALLITE_URL}/api/v1/auth/embed-token",
    json={
        "tenant_id": "acme-demo",
        "user_identity": "viewer@customer.com",
        "capabilities": ["chat"],
        "expiry_minutes": 60,
    },
    cookies=cookies,
)
embed_token = resp.json()["token"]

Example: curl

# Get admin session cookie
curl -s -c cookies.txt -X POST http://localhost:3000/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"tenant_id":"acme-demo","email":"admin@acme-demo.com","password":"acme-demo"}'

# Request embed token
curl -s -b cookies.txt -X POST http://localhost:3000/api/v1/auth/embed-token \
  -H 'Content-Type: application/json' \
  -d '{
    "tenant_id": "acme-demo",
    "user_identity": "demo-viewer",
    "capabilities": ["query", "chat"],
    "expiry_minutes": 180
  }'

Security considerations

Related