Embed mode
Drop McNif into the product you already have.
A short-lived, HMAC-signed token and an <iframe> render a
chrome-less McNif view right inside your own app — tenant-scoped, RBAC-enforced, and live today.
Why embed?
Bring the CRM to your users
Most CRMs make your customers leave to use them. Embed mode goes the other way — McNif lives inside the product they already trust.
One consistent UI
Your users see a single, coherent product — McNif renders chrome-less inside your own panel, styled to sit in your interface, not a second app bolted on the side.
No tool switching
Customers manage contacts and deals without ever leaving the product they logged into. The CRM is a panel in your app, not a tab they have to remember to open.
Keep customers in your product
Every interaction stays on your domain. You keep ownership of the relationship and the surface, while McNif does the CRM heavy lifting underneath.
How it works
Three steps to a live embed
- 1
Your backend mints a token
A short-lived HS256 token (15-minute TTL) is signed with a per-tenant secret your backend holds — never the browser. Claims pin the tenant, host origin, user, and scope.
- 2
An iframe loads the view
You drop an <iframe> pointing at /embed/contacts with the token attached. McNif verifies the signature and expiry, then renders a chrome-less contacts view.
- 3
Data flows, scoped to the tenant
The relay scopes every query to the token’s verified tenant_id, with the same RBAC as the full app. postMessage events keep the iframe sized to its content.
Integration guide
Two snippets to wire it up
Your backend mints the token; an iframe carries it. McNif verifies the HS256 signature and 15-minute expiry on every request.
<iframe id="mcnif" style="width:100%;border:0;min-height:600px" referrerpolicy="origin"></iframe>
<script>
(async () => {
const { token } = await fetch('/api/mcnif-embed-token').then(r => r.json())
document.getElementById('mcnif').src =
'https://crm.mcnifglobal.com/embed/contacts?token=' + encodeURIComponent(token)
})()
</script> const crypto = require('crypto')
const SECRET = process.env.EMBED_SIGNING_SECRET // the 128-hex per-tenant secret
const TENANT_ID = '8e12fc2c-a7b0-44ca-8b4d-5ef5a4715dc4'
function b64url(input) {
return Buffer.from(input).toString('base64')
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
}
function mintEmbedToken(user) {
const now = Math.floor(Date.now() / 1000)
const claims = {
iss: 'tenant:' + TENANT_ID,
sub: 'user:' + user.id,
iat: now,
exp: now + 900, // 15 min
tenant_id: TENANT_ID,
host_origin: 'https://admin.mcnifmv.com', // MUST be in EMBED_ALLOWED_ORIGINS
user: {
id: user.id,
email: user.email,
name: user.name,
role: 'member', // member | senior | admin | owner
},
scope: ['contacts:read'], // read→view, write→edit (RBAC still applies)
embed: { view: 'contacts', filters: {} },
}
const header = b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
const body = b64url(JSON.stringify(claims))
const sig = b64url(crypto.createHmac('sha256', SECRET).update(header + '.' + body).digest())
return header + '.' + body + '.' + sig
}
// Expose to your own authenticated front-end only:
app.get('/api/mcnif-embed-token', requireYourAuth, (req, res) => {
res.json({ token: mintEmbedToken(req.user) })
})
These are the MVP loop (Phase 17.0a): one view (/embed/contacts), one tenant, one host origin.
The full guide covers the shared secret, the X-Embed-Token header, postMessage auto-resize, and expiry handling —
ask engineering for the complete integration doc.
Integration tiers
What's shipped, and what's next
We label every tier by its real status. Today, Tier 0 and Tier 1 are live — the SDK and Headless tiers are not yet available.
Tier 0 — Web app
The full CRM at crm.mcnifglobal.com. Sign in and run your whole business.
Tier 1 — Iframe embed
Embed a chrome-less McNif view inside your own admin panel with a signed token. Shipped in Phase 17.0a.
Tier 2 — SDK
A JavaScript SDK for deeper, component-level integration. In design.
Tier 3 — Headless
A headless API surface to build entirely custom front-ends on McNif data. On the roadmap.
Talk to our engineering team
Tell us about your app and your tenants. We'll walk you through minting tokens, allow-listing your origin, and going live.