Quick Start
Get Marli Running in One Afternoon
TL;DR — the integration is a single iframe, authenticated by short-lived JWTs your backend signs with a private key. Three steps, roughly one afternoon of engineering.
1Receive Your Welcome Packet
LyticaLabs gives you:
- Partner slug — kebab-case identifier (e.g.
iscream) - Embed URL —
https://alpha.lyticalabs.ai/embed/cp/{slug} - API key — 64-char hex, shown once. Save it immediately in your secrets manager.
- Approved domains — exact origins where your iframe will load.
You give LyticaLabs:
- Company name + technical contact email
- Production & staging domain(s) (e.g.
https://app.example.com) - A public JWK (RS256 or ES256) — generate with
joseoropenssl. Keep the private half in your secrets manager.
2Wire Up Your Backend (Mint Endpoint)
Expose one endpoint that the SDK calls from the browser. Use our createMarliMintHandler helper for ~10 lines of code:
import { createMarliMintHandler } from '@lyticalabs/marli-sdk/server';
export const POST = createMarliMintHandler({
partnerSlug: process.env.CP_PARTNER_SLUG!,
privateJwkJson: process.env.CP_PARTNER_PRIVATE_JWK!,
kid: process.env.CP_PARTNER_KID!,
alg: 'RS256',
resolveContext: async (request) => {
const session = await getYourSession(request);
if (!session) return null;
return {
partnerOrgId: session.activeOrg.id,
userId: session.user.id,
};
},
});Set three env vars: CP_PARTNER_SLUG, CP_PARTNER_KID, and CP_PARTNER_PRIVATE_JWK.
3Mount the Widget in Your Frontend
'use client';
import { MarliWidget } from '@lyticalabs/marli-sdk/react';
export function MarliPanel() {
return (
<MarliWidget
baseUrl="https://alpha.lyticalabs.ai"
partnerSlug="your-slug"
onMintJwt={async () => {
const res = await fetch('/api/marli-token', { method: 'POST' });
if (!res.ok) throw new Error('mint failed');
const { jwt } = await res.json();
return jwt;
}}
iframeAttrs={{
title: 'Marli',
allow: 'clipboard-read; clipboard-write',
style: { width: '100%', height: '600px', border: 'none' },
}}
/>
);
}4Provision a Customer Org
Before any user from a customer can chat, register that customer with a single server-to-server call:
curl -X POST https://alpha.lyticalabs.ai/api/v1/cp/orgs \
-H "Authorization: Bearer ${CP_PARTNER_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"partnerExternalOrgId": "publisher_12345", "name": "Acme Media"}'Idempotent — calling twice with the same ID returns 409 (org already exists).
5Test It
Open your product, send "ping" to Marli. You should see a response stream in within ~2 seconds. Then run the full pre-launch production checklist before going live.
JWT Cheat Sheet
Your JWT has exactly five payload claims: iss (your slug), iat, exp (5–15 min TTL), partnerOrgId, and userId.
Important: partnerOrgId and userId must not contain the colon character (:). If your IDs use colons, URL-encode or replace them consistently.