ID Kit
Integrating on Web (Vanilla)
For standalone web integrations, we support 2 paths:
- Widget: A plug-and-play widget that handles UI/State management for you.
- Session API: An API that gives you total control of the user journey and UI/State management.
For full examples check out this repo.
Install
Install
npm i @worldcoin/idkit-standalone
IDKitWidget
A plug-and-play widget that handles UI and state management automatically. Initialize once, then call open()
to show the verification modal.
import '@worldcoin/idkit-standalone'
// Initialize the widget
IDKit.init({
app_id: 'app_ce4cb73cb75fc3b73b71ffb4de178410',
action: 'test-action',
signal: 'user_12345',
action_description: 'Verify your World ID',
verification_level: 'orb',
handleVerify: async response => {
// Verify the proof on your backend
const verifyRes = await fetch('/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(response),
})
if (!verifyRes.ok) throw new Error('Verification failed')
},
onSuccess: response => {
console.log('Verification successful:', response)
},
})
// Trigger verification
await IDKit.open()
Session API
For custom UIs and full control over the verification flow. Create a session, display the QR code, and poll for status updates.
import '@worldcoin/idkit-standalone'
// Create a session
await IDKitSession.create({
app_id: 'app_ce4cb73cb75fc3b73b71ffb4de178410',
action: 'test-action',
signal: 'user_12345',
action_description: 'Verify your World ID',
verification_level: 'orb',
})
// Get QR code URI
const sessionURI = IDKitSession.getURI()
// Display QR code using your preferred method
// Poll for updates
const status = await IDKitSession.pollStatus()
console.log('State:', status.state) // 'awaiting_connection', 'confirmed', 'failed'
if (status.state === 'confirmed' && status.result) {
// Verify the proof on your backend
const verifyRes = await fetch('/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(status.result),
})
if (verifyRes.ok) {
console.log('Verification successful!')
} else {
console.error('Verification failed')
}
}
// Clean up when done
IDKitSession.destroy()
Backend Verification
Critical: You must verify all proofs on your backend. Never trust client-side verification alone.
Your /api/verify
endpoint should validate the World ID proof:
// Example Node.js/Express endpoint
app.post('/api/verify', async (req, res) => {
const { proof, merkle_root, nullifier_hash, verification_level } = req.body
try {
const verifyRes = await fetch('https://developer.worldcoin.org/api/v1/verify/app_your_app_id', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nullifier_hash,
merkle_root,
proof,
verification_level,
action: 'your-action',
signal: 'your-signal', // Optional: must match frontend
}),
})
if (verifyRes.ok) {
const { verified } = await verifyRes.json()
if (verified) {
// Store nullifier_hash to prevent reuse
// Grant access to user
res.json({ success: true })
} else {
res.status(400).json({ error: 'Invalid proof' })
}
} else {
res.status(400).json({ error: 'Verification failed' })
}
} catch (error) {
res.status(500).json({ error: 'Verification error' })
}
})
Important considerations:
- Store
nullifier_hash
to prevent proof reuse - Match
action
andsignal
values between frontend and backend