Web SDK
Show a Certivant verification inside your own website with one script tag — modal or inline, with ready, step, complete, cancel and error events, strict origin checks and camera support.
The Certivant web SDK is a small, dependency-free script that opens a verification inside your page — in a modal or inline in a container — and tells your code when the applicant reaches each step and when they finish. The applicant never leaves your site, and no personal data ever passes through your page: the SDK reports a step name, a final status and a public id.
It embeds the same hosted pages you can already send by link:
| You pass | Opens | Page |
|---|---|---|
token | the hosted verification | /verify/<token> |
formSlug | a public form | /forms/<slug> |
liveIdToken | the Live ID capture page | /live-id/<token> |
url | any of the above, as a full link | must be on a trusted origin |
1. Allow your website
Browsers only show a page in a frame when the page's owner agrees. In Settings → KYC → Embedding add the origins of the websites that will embed it — one per line:
https://app.example.com
https://*.example.org
http://localhost:3000
- An origin is
https://hostplus an optional:port, with no path. - A leading
*.allows every subdomain (https://*.example.org), never the bare domain and never a bare suffix such as*.com. - Plain
httpis accepted forlocalhost,127.0.0.1and[::1]only. - Up to 20 origins. Any other website sees "refused to connect".
The list applies to your organization's links only. Certivant reads it from the link's token or form slug, so one organization can never allow framing of another's pages.
2. Create the verification
Create the verification with the REST API and get its hosted token (kvs_…) — see Sessions. Do this on your server: never put an API key in the browser.
3. Add the script and open it
<script src="https://app.certivant.com/embed/certivant.js"></script>
<button id="verify">Verify my identity</button>
<script>
document.getElementById("verify").addEventListener("click", function () {
var flow = Certivant.open({
token: "kvs_…", // from your server
onReady: function () { console.log("loaded"); },
onStep: function (e) { console.log("step", e.step); },
onComplete: function (e) { console.log("done", e.status, e.requestId); },
onCancel: function () { console.log("closed"); },
onError: function (e) { console.error(e.code, e.message); }
});
});
</script>
The script's origin is the Certivant origin it frames. If you use a custom domain, load the script from it or pass origin: "https://id.yourbrand.com".
Inline
<div id="verification"></div>
<script>
Certivant.open({
mode: "inline",
container: "#verification", // element or selector
formSlug: "customer-onboarding",
locale: "fr",
minHeight: 640
});
</script>
The frame grows with its content (resize events) and never shrinks below minHeight.
Options
| Option | Type | Notes |
|---|---|---|
token / formSlug / liveIdToken / url | string | One is required. |
formKey | string | Access key for forms that need one. |
origin | string | Certivant origin to frame. Default: where the script was loaded from. |
trustedOrigins | string[] | Extra origins url may point to. |
mode | "modal" or "inline" | Default modal. |
container | Element or string | Required for inline. |
locale | string | Language of a public form link (fr, de…). Hosted verifications follow the applicant's browser language. |
theme | "light" or "dark" | Modal frame only. |
title, closeLabel | string | Accessible labels (translate them for your site). |
closeOnBackdrop | boolean | Close when the backdrop is clicked. Default false. |
minHeight | number | Inline minimum height in px. Default 600. |
loadTimeoutMs | number | Wait before reporting not_ready. Default 20000. |
Certivant.open() returns a handle: close() (reports cancel unless the flow already completed), destroy() (silent), on(event, fn), off(event, fn), plus iframe and origin.
Events
| Event | Callback | Payload |
|---|---|---|
ready | onReady | none — the page loaded and shows the flow. |
step | onStep | { step, index?, total? } — e.g. intro, upload, review; forms report page-1… |
complete | onComplete | { status, requestId? } — status is approved, rejected, escalated, submitted or pending-review. |
cancel | onCancel | none — the applicant closed the modal before finishing. |
error | onError | { code, message } — link_expired, link_cancelled, unavailable, invalid_options, untrusted_origin, not_ready. |
resize | onResize | { height } — inline mode handles it for you. |
complete means the applicant finished their part. A hosted verification reports submitted: the decision is made afterwards, so rely on the kyc.request.approved / kyc.request.rejected webhooks on your server, never on a browser event. The Live ID capture page is the exception — it answers immediately with approved (matched) or rejected.
not_ready fires when the page has not said ready after 20 seconds. The usual cause is that your website's origin is not in Embedding, or the token has already been used.
Security model
- Who may frame a page. The proxy sets
Content-Security-Policy: frame-ancestors 'self' <your origins>(and dropsX-Frame-Options) on your hosted links, forms and Live ID pages. An unknown token, an error or an empty list leaves them unframeable. Dashboard and sign-in pages are never framable. - Who the SDK trusts. The frame URL is built only from the SDK's own origin,
origin, ortrustedOrigins. A message is accepted only if it comes from that iframe's window, from the exact origin that was framed, and is a versioned{ "source": "certivant", "version": 1, … }envelope. Everything else is ignored. - Who the page talks to. The framed page posts only to the parent origin the SDK announced (
?parentOrigin=), and only when that origin is in your allowed list (or equals the page's own origin) and, where the browser exposes it, matcheslocation.ancestorOrigins. It never posts with a*target. - No personal data. Events never include names, document data, scores or images.
Camera, microphone and location
The SDK sets allow="camera; microphone; geolocation; clipboard-write" on the iframe, which delegates those permissions to the embedded page. Certivant's own Permissions-Policy allows them for its pages (camera=(self)…), so the two sides agree. Your site must itself be served over HTTPS (or localhost), and must not send a Permissions-Policy header that blocks camera or microphone.
Plain iframe
Without the SDK you can use a normal iframe — allow your origin first, and add the allow attribute:
<iframe
src="https://app.certivant.com/verify/kvs_…?embed=1&parentOrigin=https%3A%2F%2Fyour-site.example"
allow="camera; microphone; geolocation; clipboard-write"
style="width:100%;height:760px;border:0"
></iframe>
Events are posted to the parentOrigin you announce, if it is allowed; listen with window.addEventListener("message", …) and check event.origin, event.source and the envelope yourself.
Troubleshooting
| Symptom | Fix |
|---|---|
| "refused to connect" / blank frame | Add your site's origin to Settings → KYC → Embedding (check scheme and port). |
not_ready error | Same as above, or the token was already consumed or expired. |
| Camera does not start | Serve your page over HTTPS; check no Permissions-Policy header on your site blocks camera; keep the allow attribute. |
| No events arrive | The page only posts when your origin is allowed and ?embed=1&parentOrigin=… is present — use the SDK, or add the parameters yourself. |
| Custom domain | Load the script from it, or pass origin. |
Versioning
The script reports its version in Certivant.version and the X-Certivant-SDK-Version response header. The message envelope carries version: 1; additions within version 1 are backwards compatible, and a breaking change ships as version 2 with the previous version still served. The loader is cached for a few minutes.
For native apps see Mobile WebView.
Triggers
Complete reference for every Certivant Automation Workflow trigger — when each event fires, its data context, example payloads, subject/scope configuration, and DSL filter patterns.
Mobile WebView
Show a Certivant verification in a React Native or Flutter app — WebView settings, camera permissions and the same events as the web SDK, with sample code.