HappierleadsDocs
Embed Happierleads screens

Open a screen: the one-time link

One endpoint on your server asks for a link every time your page shows an embedded screen.

Add one endpoint to your server. Your page calls it every time it shows a screen; it checks your user is signed in, then asks us for a link with your embed key.

The call

POST /v3/embed/sessions, with Authorization: Bearer $HL_EMBED_KEY.

POST/v3/embed/sessionsSample data · runs on your server with your embed key
Try:
Request body
Website IdThe client's website, from your database (not needed with scope account).
ViewThe screen to open. auto: install until the pixel works, then leads.
Scopeaccount: the admin view of every website (your own staff only).
curl -X POST "https://rest-admin.happierleads.com/v3/embed/sessions" \  -H "Authorization: Bearer $HL_EMBED_KEY" \  -H "Content-Type: application/json" \  -d '{  "websiteId": "64b7f0a1c2d3e4f5a6b7c8d9",  "view": "auto"}'
Response
Press Send request to try it with sample data.

The url works once, within 60 seconds. Put it straight into the iframe; never store it, never log it.

FieldRequiredWhat it is
websiteIdYes (unless scope is account)The signed-in user's company website. Always from your database, never from the request.
viewNo, default autoThe screen to open (below).
scopeNo, default websiteaccount opens the admin view of every website of your account: your own staff only.
user.emailNoOnly if you switched on CSV export: the export's file link is emailed there. Without it the Export button is hidden.

No personal data needed

Send only the website and the screen. We never need your users' names or emails.

Which screen: view

viewOpens
autoThe install screen until their pixel works, then their leads. Use this by default.
leadsTheir leads
installThe tracking-pixel install screen: their snippet and a Verify button
automations · integrations · settings · qualify · engageAn extra screen, only if you ticked it in Embed settings

One iframe per screen, each behind its own menu item in your app.

Your endpoint

server.js
app.get('/api/leads-embed', requireLogin, async (req, res) => {
  const staff = req.user.isStaff; // your rule: who may see every website
  const view = ['auto', 'leads', 'install'].includes(req.query.view) ? req.query.view : 'auto';
  const r = await fetch(`${process.env.HL_API_BASE}/v3/embed/sessions`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.HL_EMBED_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify(staff ? { scope: 'account' } : { websiteId: req.user.company.happierleadsWebsiteId, view }),
  });
  if (!r.ok) return res.status(502).json({ error: 'Could not open this screen' });
  res.set('Cache-Control', 'no-store').json({ url: (await r.json()).url });
});
  • Not signed in: requireLogin answers 401 before anything reaches us.
  • A company with no website yet (signed up while our API was down): create it on the spot (Create a website), then continue.
  • Keep our name out of your route: /api/leads-embed, not /api/happierleads.

Errors

StatusWhyWhat to do
400Unknown view, a screen you didn't tick, or a website outside your accountCheck the status message
401Wrong or revoked embed key, or embedding is switched offCheck HL_EMBED_KEY and Embed settings

Next: show it in an iframe.

On this page