Quickstart: browser
Enroll and sign in a user from a script tag or a React app.
You need a FaceCard app and a publishable key. Create both in the developer portal:
- Create an app and add your site's origin to its allow list, for example
https://app.example.com. For local work addhttp://localhost:3000(scheme, host and port must match exactly). - Create a publishable key. It looks like
fc_pk_live_xxx. It is safe to put in browser code, but it only works from the origins you allowed.
The camera needs a secure context, so serve your page over https:// (or use localhost).
Script tag
<video id="preview" autoplay playsinline muted></video>
<button id="enroll">Create account</button>
<button id="signin">Sign in</button>
<script type="module">
import { createFaceCard } from 'https://esm.sh/@facecard/sdk@4';
const fc = createFaceCard({ publishableKey: 'fc_pk_live_xxx' });
document.getElementById('enroll').onclick = async () => {
const { user, token } = await fc.enroll({
email: 'ada@example.com',
name: 'Ada',
// Only after the user accepts your privacy notice:
consent: { policy_version: '2026-10-14', accepted: true },
});
// Send `token` to your server to start a session.
console.log('Enrolled', user.id);
};
document.getElementById('signin').onclick = async () => {
try {
const { user, token } = await fc.signIn();
console.log('Signed in', user.id);
} catch (err) {
if (err.code === 'no_match') alert('We could not recognize you. Try again.');
else throw err;
}
};
</script>If you use a bundler, install the package instead and import it the same way:
npm install @facecard/sdkReact
npm install @facecard/sdkimport { FaceCardProvider, useFaceCard } from '@facecard/sdk/react';
function SignInButton() {
const fc = useFaceCard();
async function onClick() {
const { token } = await fc.signIn();
await fetch('/api/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token }),
});
}
return <button onClick={onClick}>Sign in with your face</button>;
}
export default function App() {
return (
<FaceCardProvider publishableKey="fc_pk_live_xxx">
<SignInButton />
</FaceCardProvider>
);
}Enroll the same way with fc.enroll({ email, name, consent }).
What to do with the token
signIn() and enroll() return a user token. Treat it as proof that FaceCard matched a face in your app. Send it to your own server and verify it there (Quickstart: server). Do not trust a token that was not verified server side.
Consent
Enrollment fails with consent_required unless the user accepted your privacy notice. Show the notice before you call enroll, and pass consent: { policy_version, accepted: true } only after the user agrees, where policy_version names the notice they saw. FaceCard records the policy version, time, IP address and user agent. See Security and privacy.
Common errors
| Error code | What it means |
|---|---|
origin_not_allowed | The page origin is not on the app's allow list. |
no_match | No enrolled face matched clearly enough. Let the user retry. |
email_taken | That email is already enrolled in this app. |
face_already_enrolled | This face is already enrolled in this app. |
rate_limited | Too many attempts from this IP. Wait for Retry-After. |
The full list is in Errors.