FaceGateBack to home

Client SDK

@facegate/client is the framework-free core of FaceGate. Pure JS/TS, zero runtime dependencies. It handles camera capture, the AWS liveness flow, and all HTTP communication with the FaceGate server.

Use this package directly if you are on Vue, Svelte, Angular, or plain JavaScript. If you are on React, use @facegate/react — it wraps this client with a drop-in <FaceGate /> component and saves you the camera and state plumbing.

Install

npm install @facegate/client

Construct the client

FaceGateClient is the main class. Give it your API key. Everything else has defaults.

import { FaceGateClient } from '@facegate/client';
 
const fg = new FaceGateClient({
  apiKey: 'fg_test_your_key_here',
});

Constructor options

The constructor takes a FaceGateConfig.

OptionTypeDefaultDescription
apiKeystringRequired. fg_live_… or fg_test_….
baseUrlstringhttps://api.facegate.aiServer base URL. Trailing slash is stripped.
confidenceThresholdnumber95Face match confidence threshold (0–100).
challengeTimeoutnumber30000Liveness challenge timeout in ms.
provider'supabase' | 'auth0' | 'firebase'nullAuth provider for Tier 2 session creation. Sent with createSession().
providerConfigRecord<string, unknown>{}Provider-specific config.

The resolved config is exposed read-only on fg.config.

Methods

All network methods return promises and retry on retryable failures (GET retries 3×, mutations retry 2×, with exponential backoff). A 401 throws InvalidApiKey; non-retryable errors throw immediately.

MethodSignatureReturnsEndpoint
matchmatch({ image: string })Promise<MatchResult>POST /v1/match
createLivenessSessioncreateLivenessSession()Promise<LivenessSession>POST /v1/liveness/session
verifyverify({ livenessSessionId: string })Promise<VerifyResult>POST /v1/verify
createSessioncreateSession(verificationToken: string)Promise<FaceGateSession>POST /v1/session
enrollenroll(params)Promise<EnrollResult>POST /v1/enroll
healthhealth()Promise<HealthStatus>GET /v1/health
onon(listener)() => void (unsubscribe)

match({ image })

Match a face without liveness. A fast identity check — no anti-spoofing. image is a base64-encoded JPEG (a data: URL prefix is stripped automatically).

const result = await fg.match({ image: frame.imageData });
// result.matched    — boolean
// result.confidence — 0–100
// result.user       — MatchedUser | null

createLivenessSession()

Creates an AWS Face Liveness session. Returns the session_id, temporary AWS credentials, and region that the AWS FaceLivenessDetector UI component consumes. This is the start of a real, anti-spoofed verification.

const session = await fg.createLivenessSession();
// hand session.session_id / credentials / region to the AWS liveness UI

verify({ livenessSessionId })

Verify a face against a completed AWS liveness session. Pass the session_id from createLivenessSession() once the AWS component finishes. On success the server returns a signed verification_token you exchange for a session, plus risk and device data. The client persists the returned device_id to localStorage and emits a verified event.

const result = await fg.verify({ livenessSessionId: session.session_id });
// result.matched               — boolean
// result.confidence            — 0–100
// result.verification_token    — string | null  (use with createSession)
// result.user                  — MatchedUser | null
// result.risk                  — RiskAssessment
// result.re_enrollment_required — boolean

createSession(verificationToken)

Exchange a verification_token from a successful verify() for an auth session. If a provider was set on the client, the returned FaceGateSession.provider_session carries that provider's tokens (e.g. Supabase). Emits a session_created event.

const fgSession = await fg.createSession(result.verification_token!);
// fgSession.token            — signed JWT
// fgSession.refresh_token    — string
// fgSession.expires_in       — seconds
// fgSession.user             — MatchedUser
// fgSession.provider_session — provider tokens | null

enroll(params)

Enroll a new face. Provide either a completed livenessSessionId (anti-spoofed enrollment) or a raw image, plus a name.

ParamTypeRequiredDescription
livenessSessionIdstringone of these twoCompleted AWS liveness session.
imagestringone of these twoBase64 face image.
namestringyesPerson's name.
rolestringnoRole assignment. Defaults to 'user'.
externalIdstringnoYour own ID for this user.
emailstringnoUser email.
consentIdstringnoBiometric consent record ID.
metadataRecord<string, unknown>noArbitrary metadata.
const enrolled = await fg.enroll({
  livenessSessionId: session.session_id,
  name: 'Ada Lovelace',
  role: 'admin',
});
// enrolled.user_id     — string
// enrolled.enrollments — { faceId, angle, confidence }[]

health()

Server health check.

const status = await fg.health();
// status.status         — 'healthy' | 'degraded' | 'unhealthy'
// status.version, status.provider, status.uptime_seconds

on(listener)

Subscribe to client events. Returns an unsubscribe function. Events are FaceGateEvent — including verified, session_created, camera_ready, and error.

const off = fg.on((event) => {
  if (event.type === 'verified') console.log('confidence', event.data.confidence);
});
// later: off();

The Camera class

Camera is the only module that touches navigator.mediaDevices. It opens a stream, attaches it to a <video> element, and grabs JPEG frames. Use it when you are building your own capture UI (the React SDK does this for you).

import { Camera } from '@facegate/client';

Static methods

MethodReturnsDescription
Camera.isAvailable()booleanIs the MediaDevices API present in this browser.
Camera.listDevices()Promise<CameraDevice[]>List video input devices with inferred facing.

Instance methods

MemberSignatureDescription
openopen(deviceId?: string): Promise<MediaStream>Request permission and start the stream. Throws CameraPermissionDenied / CameraUnavailable / CameraError.
attachToVideoattachToVideo(video: HTMLVideoElement): voidBind the stream to a <video> element for rendering and capture.
captureFramecaptureFrame(): CapturedFrameGrab a single JPEG frame from the attached video.
captureFramescaptureFrames(count: number, intervalMs: number): Promise<CapturedFrame[]>Grab multiple frames over time.
closeclose(): voidStop tracks and release the camera.
streamget stream(): MediaStream | nullThe active stream, or null.
isReadyget isReady(): booleanWhether a video element is attached and ready for capture.

A CapturedFrame is { imageData, timestamp, width, height }, where imageData is a base64-encoded JPEG data: URL.

const camera = new Camera();
await camera.open();                 // permission + stream
camera.attachToVideo(videoElement);  // <video> in your DOM
const frame = camera.captureFrame(); // CapturedFrame
camera.close();                      // release

End-to-end example

Camera → capture → match. This is the fast identity-check path (no liveness). For a full anti-spoofed flow, swap the match() call for the AWS liveness session + verify() + createSession() sequence shown in the REST API docs.

import { FaceGateClient, Camera, CameraPermissionDenied } from '@facegate/client';
 
const fg = new FaceGateClient({ apiKey: 'fg_test_your_key_here' });
 
async function signIn(videoEl: HTMLVideoElement) {
  const camera = new Camera();
 
  try {
    // 1. Open the camera and render it
    await camera.open();
    camera.attachToVideo(videoEl);
 
    // 2. Wait for the video to be ready, then capture a frame
    await new Promise<void>((resolve) => {
      if (camera.isReady) return resolve();
      videoEl.onloadeddata = () => resolve();
    });
    const frame = camera.captureFrame();
 
    // 3. Match the face
    const result = await fg.match({ image: frame.imageData });
 
    if (!result.matched || result.confidence < 95) {
      console.log('Not recognized');
      return null;
    }
 
    // 4. Handle the matched user
    console.log('Welcome back,', result.user?.name);
    return result.user;
  } catch (err) {
    if (err instanceof CameraPermissionDenied) {
      console.error('Camera permission was denied');
    } else {
      console.error('Sign-in failed', err);
    }
    return null;
  } finally {
    camera.close();
  }
}

Full verification flow

For real authentication, run the liveness path. createLivenessSession() hands off to the AWS FaceLivenessDetector UI; once it completes you call verify() with the same session ID, then exchange the token for a session.

// 1. Start an AWS liveness session
const session = await fg.createLivenessSession();
 
// 2. Run the AWS FaceLivenessDetector component with session.credentials / region.
//    When it completes successfully, you have session.session_id.
 
// 3. Verify the result
const result = await fg.verify({ livenessSessionId: session.session_id });
if (!result.matched) throw new Error('Face not recognized');
 
// 4. Exchange the token for a session
const fgSession = await fg.createSession(result.verification_token!);
console.log('JWT:', fgSession.token);

Error types

Network and camera failures throw typed errors, all subclasses of FaceGateError: CameraError, CameraPermissionDenied, CameraUnavailable, LivenessTimeout, LivenessFailed, VerificationFailed, ApiError, NetworkError, HandoffExpired, and InvalidApiKey. Each carries a code and a retryable flag.

Next steps

  • React SDK — if you are on React, skip the manual camera and state wiring.
  • REST API — the endpoints each method calls, for direct integration.