EmbeddingWeb SDK

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 passOpensPage
tokenthe hosted verification/verify/<token>
formSluga public form/forms/<slug>
liveIdTokenthe Live ID capture page/live-id/<token>
urlany of the above, as a full linkmust 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://host plus 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 http is accepted for localhost, 127.0.0.1 and [::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

OptionTypeNotes
token / formSlug / liveIdToken / urlstringOne is required.
formKeystringAccess key for forms that need one.
originstringCertivant origin to frame. Default: where the script was loaded from.
trustedOriginsstring[]Extra origins url may point to.
mode"modal" or "inline"Default modal.
containerElement or stringRequired for inline.
localestringLanguage of a public form link (fr, de…). Hosted verifications follow the applicant's browser language.
theme"light" or "dark"Modal frame only.
title, closeLabelstringAccessible labels (translate them for your site).
closeOnBackdropbooleanClose when the backdrop is clicked. Default false.
minHeightnumberInline minimum height in px. Default 600.
loadTimeoutMsnumberWait 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

EventCallbackPayload
readyonReadynone — the page loaded and shows the flow.
steponStep{ step, index?, total? } — e.g. intro, upload, review; forms report page-1…
completeonComplete{ status, requestId? } — status is approved, rejected, escalated, submitted or pending-review.
cancelonCancelnone — the applicant closed the modal before finishing.
erroronError{ code, message } — link_expired, link_cancelled, unavailable, invalid_options, untrusted_origin, not_ready.
resizeonResize{ 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 drops X-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, or trustedOrigins. 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, matches location.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

SymptomFix
"refused to connect" / blank frameAdd your site's origin to Settings → KYC → Embedding (check scheme and port).
not_ready errorSame as above, or the token was already consumed or expired.
Camera does not startServe your page over HTTPS; check no Permissions-Policy header on your site blocks camera; keep the allow attribute.
No events arriveThe page only posts when your origin is allowed and ?embed=1&parentOrigin=… is present — use the SDK, or add the parameters yourself.
Custom domainLoad 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.