stile
SDKs

Widget SDK

Framework-agnostic web component and JavaScript API for embedding verification in any frontend.

Installation

<script src="https://cdn.stile.dev/v1/stile.js"></script>
npm install @stile/widget

Quick start: <stile-button>

The simplest integration — a drop-in web component that handles the entire verification flow. Works with any framework or plain HTML.

<stile-button
  publishable-key="pk_test_..."
  email-selector="#checkout-email"
></stile-button>

Attributes

ParameterTypeDescription
publishable-keyrequiredstringYour publishable key (pk_test_ or pk_live_).
email-selectorstringCSS selector for an email input on the page. The button reads its value automatically.
emailstringPass the email directly instead of using a selector.
use-casestringOverride the default use case for this key.
labelstring= "Verify Age"Button text.
verified-labelstring= "Age Verified"Text shown after successful verification.
disabledbooleanDisable the button.

Events

Listen for custom events on the <stile-button> element:

EventDetailDescription
stile:verifiedVerifyResultVerification succeeded.
stile:error{ message: string }Verification failed.
stile:cancelUser closed the modal.
const btn = document.querySelector("stile-button");

btn.addEventListener("stile:verified", (e) => {
  console.log("Verified!", e.detail);
  // e.detail.sessionId, e.detail.status, etc.
});

btn.addEventListener("stile:error", (e) => {
  console.error("Failed:", e.detail.message);
});

btn.addEventListener("stile:cancel", () => {
  console.log("User cancelled");
});

verify() — JavaScript API

For more control, use the verify() function directly. It opens a modal, handles the entire flow, and returns a promise.

import { verify } from "@stile/widget";

const result = await verify({
  publishableKey: "pk_test_...",
  email: "user@example.com",
  useCase: "alcohol_delivery",
});

console.log(result.sessionId, result.status);
ParameterTypeDescription
publishableKeyrequiredstringYour publishable key.
emailrequiredstringThe user's email address.
useCasestringOverride the default use case.
jurisdictionstringOverride the jurisdiction.

The promise rejects with a VerifyError if the user cancels (error.reason === "cancelled") or if verification fails.

create() — Low-level API

For fully custom UIs, use create() to manage the widget lifecycle yourself. This is useful when you create sessions on your own backend and pass the client_secret to the frontend.

import { create } from "@stile/widget";

const widget = create({
  clientSecret: session.client_secret,  // from your backend
  container: document.getElementById("verify-container"),
  onComplete: (session) => {
    console.log("Verified!", session.id);
  },
  onError: (error) => {
    console.error("Failed:", error.message);
  },
  onCancel: () => {
    console.log("User cancelled");
  },
});

Framework examples

The web component works natively in any framework:

export function Checkout() {
  return (
    <stile-button
      publishable-key="pk_test_..."
      email="user@example.com"
    />
  );
}
<template>
  <stile-button
    publishable-key="pk_test_..."
    :email="userEmail"
  />
</template>
<stile-button
  publishable-key="pk_test_..."
  email={userEmail}
/>
<stile-button
  publishable-key="pk_test_..."
  email-selector="#email"
></stile-button>

Web components are supported in all modern browsers. The <stile-button> element auto-registers when the script loads — no setup required.

On this page