Building a native mobile app or a fully custom UI without the widget? See Direct API (No SDK) — the same flow driven with plain REST calls.
Quick Start (Node.js SDK)
bashnpm install @flonkid/kyc
| Import | Use |
|---|---|
@flonkid/kyc | Browser — widget iframe + postMessage |
@flonkid/kyc/server | Node.js — sessions API + webhook verification |
@flonkid/kyc/types | TypeScript types only |
1. Backend: Create session endpoint
Your backend creates a KYC session using the secret key, then returns sessionId + embedToken (+ qrCodeUrl for the mobile-transfer QR) to the frontend.
typescript1import { FlonkKYCServer } from '@flonkid/kyc/server';23const flonk = new FlonkKYCServer({4 secretKey: process.env.FLONK_SECRET_KEY!,5 // apiBase: 'https://api.flonk.id/v1', // optional, default6});78// Express / Next.js API route9app.post('/api/kyc/create-session', async (req, res) => {10 try {11 const session = await flonk.createSession({12 clientMetadata: req.body.clientMetadata,13 expiryMinutes: 30,14 language: 'de',15 });1617 // Return what the browser SDK needs. Map `id` → `sessionId`, and include18 // `qrCodeUrl` so the desktop→mobile QR renders.19 res.json({20 sessionId: session.id,21 embedToken: session.embedToken,22 qrCodeUrl: session.qrCodeUrl,23 });24 } catch (err) {25 console.error('Session creation failed:', err.message);26 res.status(err.statusCode || 500).json({ error: err.message });27 }28});
2. Frontend: Start KYC
The snippets below are React. Vue / Svelte / Angular use the same
FlonkKYCclass imported from@flonkid/kyc/core(the React-free entry — see Frontend SDK), and no-build pages (WordPress, Rails, plain HTML) load one<script>tag from the API — see Script Tag (No Build Step). The session flow (A vs B) below is identical across all of them.
There are two integration approaches. Choose one:
Option A: SDK handles everything (serverUrl)
SDK auto-creates the session via your backend endpoint, opens the widget, and handles cleanup. Simplest approach — one component, zero state management.
If your backend requires authentication, pass requestHeaders:
tsx<FlonkKYCWidgetpublishableKey="pk_live_..."serverUrl="/api/kyc/create-session"requestHeaders={{ Authorization: `Bearer ${token}` }}.../>
publishableKeyloads your project branding (colors, logo) instantly while the session is being created. Find it in Dashboard → API Keys.
tsx1import { FlonkKYCWidget } from '@flonkid/kyc';23export default function KYCVerification() {4 return (5 <FlonkKYCWidget6 publishableKey="pk_live_..."7 serverUrl="/api/kyc/create-session"8 clientMetadata={{9 email: 'user@example.com',10 userId: 'user_123', // optional11 }}12 lang="de"13 onSuccess={(result) => console.log('KYC completed:', result)}14 onError={(error) => console.error('KYC failed:', error)}15 onCancel={() => console.log('KYC cancelled')}16 />17 );18}1920// With authentication (JWT)21function KYCWithAuth({ token }: { token: string }) {22 return (23 <FlonkKYCWidget24 publishableKey="pk_live_..."25 serverUrl="/api/kyc/create-session"26 requestHeaders={{ Authorization: `Bearer ${token}` }}27 lang="de"28 onSuccess={(result) => console.log('KYC completed:', result)}29 onError={(error) => console.error('KYC failed:', error)}30 onCancel={() => console.log('KYC cancelled')}31 />32 );33}
React →
@flonkid/kyc. Vue / Angular / vanilla →FlonkKYCfrom@flonkid/kyc/core(React-free). No build step → one<script>tag fromhttps://api.flonk.id/v1/public/widget-v2.js, driven through thewindow.KYCWidgetglobal (full reference).
Option B: You control session creation (sessionId + embedToken)
Your frontend creates the session first (via your API), then passes credentials to the widget. More control — you decide when and how to create sessions.
Best for:
- Custom UI before verification (e.g. confirmation screen, age check)
- Conditional session creation (e.g. only after payment)
- Existing backend API integration
tsximport { FlonkKYCWidget } from '@flonkid/kyc';function KYCVerification() {const [session, setSession] = useState(null);const startKYC = async () => {// Your backend creates the sessionconst res = await fetch('/api/kyc/create-session', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ email: user.email }),});const data = await res.json();setSession(data); // { sessionId, embedToken, qrCodeUrl }};return (<><button onClick={startKYC}>Start Verification</button>{session && (<FlonkKYCWidgetsessionId={session.sessionId}embedToken={session.embedToken}qrCodeUrl={session.qrCodeUrl}lang="de"onSuccess={(result) => {setSession(null);console.log('Verified:', result);}}onError={(error) => {setSession(null);console.error('Failed:', error);}}onCancel={() => setSession(null)}/>)}</>);}
Which one to choose?
Option A (serverUrl) | Option B (sessionId + embedToken) | |
|---|---|---|
| Setup | 1 component | Button + state + API call + component |
| Control | SDK manages session lifecycle | You manage session lifecycle |
| Best for | Quick integration, simple flows | Custom UX, conditional flows |
| Auth | requestHeaders prop | Your own fetch with auth |
3. Webhooks: Handle verification results
Verify the HMAC-SHA256 signature, then process the event.
typescript1import { FlonkKYCServer } from '@flonkid/kyc/server';23const flonk = new FlonkKYCServer({4 secretKey: process.env.FLONK_SECRET_KEY!,5});67// Express webhook handler (use raw body for signature verification)8app.post('/webhooks/kyc',9 express.raw({ type: 'application/json' }),10 (req, res) => {11 const signature = req.headers['x-signature-256'] as string;1213 try {14 // Automatically detects signature format (sha256= or t=...,v1=...)15 const event = flonk.webhooks.constructEvent(16 req.body.toString(),17 signature,18 process.env.FLONK_WEBHOOK_SECRET!,19 );2021 // Process the verified event22 const verification = event.data.object;23 console.log(`Verification ${verification.id}: ${verification.status}`);24 console.log('Extracted data:', verification.extracted_data);2526 res.sendStatus(200);27 } catch (err) {28 console.error('Webhook verification failed:', err instanceof Error ? err.message : err);29 res.sendStatus(400);30 }31 }32);
Detailed documentation: Webhooks Integration →