@ivorycom/embed-node
v0.1.1
Published
Server SDK to mint Ivorycom embed sessions for @ivorycom/embed. Zero dependencies.
Maintainers
Readme
@ivorycom/embed-node
Server SDK to mint short‑lived Ivorycom embed session tokens for @ivorycom/embed. Your embed app secret stays on your server (OAuth2 client‑credentials style); the browser only ever receives a short‑lived, scope‑bounded token. Zero dependencies — native fetch on Node ≥ 18.
Installation
npm install @ivorycom/embed-nodeQuick start
import { createEmbedClient } from "@ivorycom/embed-node";
const embed = createEmbedClient({
clientId: process.env.IVORY_EMBED_CLIENT_ID!, // iem_… (public)
clientSecret: process.env.IVORY_EMBED_SECRET!, // ies_… (SECRET — server only)
});
// For a signed-in user in YOUR app, mint an embed session:
const { embedToken, expiresIn } = await embed.mintSession({
sub: user.id, // your stable user id
email: user.email,
name: user.name,
scopes: ["leads", "pipeline"], // subset of the app's enabled scopes
});
// Hand `embedToken` to the browser → <ivory-crm token={embedToken}>Express example
import express from "express";
import { createEmbedClient, EmbedMintError } from "@ivorycom/embed-node";
const embed = createEmbedClient({
clientId: process.env.IVORY_EMBED_CLIENT_ID!,
clientSecret: process.env.IVORY_EMBED_SECRET!,
});
const app = express();
// Called by YOUR frontend for the currently signed-in user.
app.post("/api/ivory-embed-token", requireYourAuth, async (req, res) => {
try {
const session = await embed.mintSession({
sub: req.user.id,
email: req.user.email,
name: req.user.name,
scopes: ["leads", "pipeline"],
});
res.json(session); // { embedToken, expiresIn }
} catch (err) {
if (err instanceof EmbedMintError) {
return res.status(502).json({ error: "embed_mint_failed", status: err.status });
}
throw err;
}
});API
createEmbedClient(config): EmbedClient
| config field | Type | Description |
| --- | --- | --- |
| clientId | string (required) | Your embed app's public id (iem_…). |
| clientSecret | string (required) | The embed app secret (ies_…). Never expose to the browser. |
| baseUrl | string | Ivorycom API base. Default https://api.ivorycomcrm.com. |
| fetch | typeof fetch | Custom fetch impl (for Node < 18 or testing). |
Throws TypeError if clientId/clientSecret are missing, or if no fetch is available.
client.mintSession(input): Promise<EmbedSession>
| input field | Type | Description |
| --- | --- | --- |
| sub | string (required) | Your stable user identifier. A JIT Ivorycom user is provisioned/mapped under the app's tenant. |
| email | string | User email (kept in sync on the Ivorycom side). |
| name | string | Display name. |
| scopes | string[] | Scopes to grant this session — must be a subset of the embed app's enabled scopes. Omit to inherit the app's full enabled set. |
Returns EmbedSession:
interface EmbedSession {
embedToken: string; // hand this to <ivory-crm token="…">
expiresIn: number; // seconds until expiry (default 900 = 15 min)
}EmbedMintError
Thrown when the mint request fails. Carries the HTTP status and raw body:
class EmbedMintError extends Error {
readonly status: number;
readonly body: string;
}Scopes
Grant an embed a subset of the tenant's plan using the coarse scope vocabulary:
leads · contacts · pipeline · inbox · activity · reports · campaigns · automations · agent (or * for all)
Enforcement is default‑closed and server‑side across every Ivorycom service — a token can only reach the areas you grant, and never beyond the tenant's subscription tier. scopes on mintSession must be within the embed app's enabled scopes (which you set when you register the app).
Security
- Keep the secret server‑side.
clientSecretis presented over TLS from your backend only (headersX-Embed-Key/X-Embed-Secret). Never ship it to the browser or a mobile app. - Short‑lived tokens. Sessions default to 15 minutes; mint on demand rather than caching.
- Least privilege. Grant the narrowest
scopesthe surface needs.
Requirements
- Node ≥ 18 (uses the built‑in global
fetch). On older runtimes, passconfig.fetch. - Zero runtime dependencies.
Related
@ivorycom/embed— the browser SDK (<ivory-crm>web component + React wrapper).
License
MIT © Ivorycom
