Early access. The sandbox is open now; production keys open at launch. How going live works

The embed quickstart

For product and engineering teams · Updated 29 September 2026 · Every call below is in the OpenAPI spec

You can add an anonymous three-question wellbeing check-in to your product with one iframe and three API calls.

Two of the calls run on your server when a person opens the check-in. The third reads the results for the employer. The iframe shows a check-in page that the Intelligent Wellbeing Engine hosts, so you do not build question screens, scoring or crisis signposting. Everything on this page works against the free sandbox today. The sandbox's database is hosted in London (UK) and its API runs in Dublin (Ireland). Production is designed to use the same regions.

In short: swap your client keys for a token, ask for a ten-minute embed token for the signed-in person, put the returned embed_url in an iframe, and read organisation-level results from GET /aggregates. Your client secret never reaches a browser.

Before you start: sandbox keys

Sandbox keys are self-serve. One call returns them, with no contract and no sales call:

curl -s -X POST https://sandbox.wellbeingengine.io/sandbox/signups \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com"}'

The response holds a client_id and a client_secret. The secret is shown once, so store it in a server-side environment variable straight away. Sandbox keys last 30 days and work against a synthetic workforce. They carry a quota of 2,000 writes: each embed token counts one, and answers given inside the hosted check-in do not count. The response lists three synthetic people, syn-normal-01 to syn-normal-03; the seeded syn-normal unit holds twelve, up to syn-normal-12. In the sandbox, questions the IWE wrote show placeholder wording. Details are in the integration guide.

Call 1: get an access token

Your server swaps the client keys for a bearer token. It lasts one hour, so cache it and refresh it a few minutes early.

curl -s -X POST https://sandbox.wellbeingengine.io/oauth/token \
  -H 'Content-Type: application/json' \
  -d '{"grant_type":"client_credentials","client_id":"sbx_...","client_secret":"iwe_sbx_..."}'

# 200
{ "access_token": "<RS256 JWT>", "token_type": "Bearer", "expires_in": 3600, "scope": "..." }

Call 2: request an embed token for one person

When a signed-in person opens the check-in, your server asks for an embed token. Identify the person by a stable, opaque ID from your own system. Never send a name or an email address. The gateway turns the ID into a keyed pseudonym before anything is stored.

curl -s -X POST https://sandbox.wellbeingengine.io/embed/tokens \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"respondent_ref":{"partner_user_id":"syn-normal-01"}}'

# 200
{ "token": "<RS256 JWT>",
  "embed_url": "https://sandbox.wellbeingengine.io/checkin?token=...",
  "expires_at": "<now + 10 minutes>" }

The embed token lasts ten minutes and can only drive that one person's check-in. Always use the embed_url the API returns. A 404 means the person is not on the engine's roster yet. In production you add people with POST /respondents:sync; in the sandbox you use the synthetic IDs.

The iframe

Your page opens the embed_url in a plain iframe. There is no package to install. These few lines are the whole front end:

const frame = document.createElement('iframe');
frame.src = tok.embed_url;             // fetched from YOUR backend
frame.referrerPolicy = 'no-referrer';
frame.style.cssText = 'width:100%;min-height:520px;border:0';
document.querySelector('#wellbeing').appendChild(frame);

const embedOrigin = new URL(tok.embed_url).origin;
let answersSaved = false;
window.addEventListener('message', (e) => {
  if (e.origin !== embedOrigin || e.source !== frame.contentWindow) return;
  if (e.data?.source !== 'iwe-embed') return;
  if (e.data.type === 'dismissed') { frame.remove(); return; }
  if (e.data.type === 'completed') {
    if (answersSaved) { frame.remove(); }   // the person pressed Close
    answersSaved = true;                     // thank-you screen is showing: leave it open
  }
});

Accept only messages from the embed origin, sent by your frame, with source: "iwe-embed". Keep the frame open after the first completed, because the thank-you screen it announces carries the crisis signposting. The check-in sends completed again when the person presses Close; remove the frame then, or on dismissed. Put your own Close button next to the frame as well: if the embed token has expired, the check-in shows an error and sends no message, and the person still needs a way out. Treat the events as hints for your interface. The API is the record of what was answered.

Call 3: read the results

The employer's view reads organisation-level results. Each row carries its value, its 95% confidence interval, the group size n, the headcount and the completion rate.

curl -s "https://sandbox.wellbeingengine.io/aggregates?unit_id=syn-normal" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# 200, one row per organisation, round and metric
[ { "metric": "WELLBEING_INDEX", "n": 11, "headcount": 12, "completion_rate": "0.917",
    "suppressed": false, "value": "71", "ci_low": "63.4", "ci_high": "78.6",
    "method": "design", ... },
  { "metric": "DOMAIN_MEAN", "question_code": "SLEEP_QUALITY_1", "n": 4,
    "suppressed": true, "suppression_reason": "below-floor",
    "value": null, "ci_low": null, "ci_high": null, ... } ]

Decimal fields arrive as JSON strings, so parse value, ci_low, ci_high, sd and completion_rate before you do arithmetic. The unit_id you send is your own reference; the unit_id in each row is the engine's unit UUID.

Your results view has three jobs. Put the interval beside every value. Add a provisional badge when method is indicative, which means five to nine people. Show a withheld row as withheld, with its reason and no number anywhere on the page. Try unit_id=syn-tiny to see a group where every figure is withheld.

What the person sees

Rules your integration keeps

Try it

Native apps and kiosks

If you cannot use an iframe, your server can drive the same check-in through the API. Read the person's state with GET /respondents/{id}/checkin and send each answer with POST /respondents/{id}/answers. Your product then draws the screens, so the obligations the hosted page covers become yours. The guide lists them.

Next: the full integration guide · pricing (10p per enrolled user per month, £250 monthly minimum in production) · how going live works · for HR, rota, intranet and learning platforms · for EAP and occupational health providers