cimplify
Cimplify Link

AuthElement

A single-line OTP sign-in component. Customer types an email or phone number, presses submit, types the 6-digit code, and the Element emits an `authenticated` event with a Link session token. Use it standalone (e.g. on a login page) or alongside other Elements (the parent controller broadcasts the token to them automatically).

Iframe URL

https://link.cimplify.io/elements/auth?businessId=biz_…&nonce=<random>&email=<optional prefill>

Authentication flow

  1. Element loads, posts ready, parent replies with init.
  2. If a Link cookie is present on link.cimplify.io, the Element silently re-authenticates and emits authenticated immediately. No user interaction needed.
  3. Otherwise the customer enters a contact (email or phone). The Element posts to POST /v1/link/elements/request-otp and emits requires_otp.
  4. Customer types the 6-digit code. The Element posts to POST /v1/link/elements/verify-otp; on success emits authenticated with the token, accountId, customerId, and customer profile.

React

import {
  ElementsProvider,
  AuthElement,
} from "@cimplify/sdk/react";

<ElementsProvider client={client}>
  <AuthElement
    prefillEmail="jane@example.com"
    onReady={() => setReady(true)}
    onRequiresOtp={({ contactMasked }) => setStatus(`Code sent to ${contactMasked}`)}
    onAuthenticated={({ token, accountId, customerId, customer }) => {
      setToken(token);
      setCustomer(customer);
    }}
    onError={(err) => setError(err.message)}
  />
</ElementsProvider>

Props

PropTypeNotes
className / styleApplied to the wrapper <div> hosting the iframe.
prefillEmailstringPre-fills the contact field.
onReady() => voidiframe interactive.
onRequiresOtp(d: { contactMasked }) => voidOTP dispatched.
onAuthenticated(d: AuthenticatedData) => voidToken + customer.
onError(err: { code, message }) => voidAny failure.

AuthenticatedData

interface AuthenticatedData {
  accountId: string;
  customerId: string;
  token: string;
  customer: { name: string; email: string | null; phone: string | null };
}

Vanilla

import { createElements, ELEMENT_TYPES, EVENT_TYPES } from "@cimplify/sdk";

const elements = createElements(client, businessId);
const auth = elements.create(ELEMENT_TYPES.AUTH, { prefillEmail: "jane@…" });

auth.on(EVENT_TYPES.AUTHENTICATED, (data) => {
  // data: AuthenticatedData
  setToken(data.token);
});

auth.on(EVENT_TYPES.REQUIRES_OTP, ({ contactMasked }) => {
  setStatus(`Code sent to ${contactMasked}`);
});

auth.mount("#auth-container");

Standalone iframe

<iframe
  src="https://link.cimplify.io/elements/auth?businessId=biz_…&nonce=ab12cd34"
  style="border:0; width:100%; min-height:160px"
  sandbox="allow-scripts allow-same-origin allow-forms"
></iframe>

Test mode

When publicKey begins with pk_test_, the Element pre-fills +233200000001 as the contact and shows a banner. Use the test phone numbers and OTP 123456 documented under environments.

Logout

Send { type: "logout" } from the parent. The Element clears its session cookie via POST /v1/link/elements/logout and emits logout_complete.

What it does NOT do

  • No social sign-in (Google / Apple / Facebook). OTP only.
  • No magic-link email. The verification is always a 6-digit code.
  • No password fallback.
  • No biometric / WebAuthn step. Trust is rooted in possession of the contact channel.

Next

On this page