| Fast | Balanced Recommended | Thorough | Extended | Maximum | |
|---|---|---|---|---|---|
| Model ID | mixed-10-v2 |
mixed-30-v2 |
mixed-60-v2 |
mixed-90-v2 |
mixed-120-v2 |
| Frames | 10 | 30 | 60 | 90 | 120 |
| Capture time | ~0.3 s | ~1 s | ~2 s | ~3 s | ~4 s |
| Response time | ~1 s | ~3 s | ~5 s | ~7 s | ~10 s |
| EER | 4.4% | 4.0% | 4.7% | 5.7% | 4.6% |
| AUC | 0.988 | 0.991 | 0.991 | 0.989 | 0.991 |
| Balanced accuracy | 95.2% | 95.7% | 95.2% | 94.3% | 94.7% |
| Best for | Low-friction, high-volume flows | Standard KYC & identity verification | High-security onboarding | Escalation, compliance-heavy flows | Highest scrutiny, regulatory edge cases |
| Fast (V3) | Balanced (V3) | Thorough (V3) | |
|---|---|---|---|
| Model ID | mixed-10-v3 |
mixed-30-v3 |
mixed-60-v3 |
| Frames | 10 | 30 | 60 |
| Notes | Often visual-only | Often visual-only | Full temporal-physio fusion |
| 10f | 30f | 60f | 90f | |
|---|---|---|---|---|
| Model ID | mixed-10-v3_1 |
mixed-30-v3_1 |
mixed-60-v3_1 |
mixed-90-v3_1 |
| Frames | 10 | 30 | 60 | 90 |
| Recommended for | Lowest latency, new integrations | Default V3.1 choice | Best attack rejection (V3.1) | Extended temporal coverage |
| 10f | 30f | 60f | 90f Recommended | 120f | |
|---|---|---|---|---|---|
| Model ID | mixed-10-v3_1_1 |
mixed-30-v3_1_1 |
mixed-60-v3_1_1 |
mixed-90-v3_1_1 |
mixed-120-v3_1_1 |
| Frames | 10 | 30 | 60 | 90 | 120 |
| Recommended for | Lowest latency, new integrations | Default V3.1.1 choice | High-security onboarding | Best overall accuracy (ship config) | Maximum temporal coverage |
| Model ID | mixed-10-v2 |
| Frames required | 10 |
| Capture time | ~0.3 seconds at 30 FPS |
| Avg response time | ~1s |
| Security level | Strong |
| EER | 4.4% |
| AUC | 0.988 |
| Balanced accuracy | 95.2% |
| Avg response (fast-check) | ~1s |
| Avg response (fast-check-crops) | ~1s |
| Model ID | mixed-30-v2 |
| Frames required | 30 |
| Capture time | ~1 second at 30 FPS |
| Avg response time | ~3s |
| Security level | Strongest |
| EER | 4.0% |
| AUC | 0.991 |
| Balanced accuracy | 95.7% |
| Avg response (fast-check) | ~3s |
| Model ID | mixed-60-v2 |
| Frames required | 60 |
| Capture time | ~2 seconds at 30 FPS |
| Avg response time | ~5s |
| Security level | Strong |
| EER | 4.7% |
| AUC | 0.991 |
| Balanced accuracy | 95.2% |
| Avg response (fast-check) | ~5s |
| Model ID | mixed-90-v2 |
| Frames required | 90 |
| Capture time | ~3 seconds at 30 FPS |
| Avg response time | ~7s |
| Security level | Strong |
| EER | 5.7% |
| AUC | 0.989 |
| Balanced accuracy | 94.3% |
| Avg response | ~7s |
| Model ID | mixed-120-v2 |
| Frames required | 120 |
| Capture time | ~4 seconds at 30 FPS |
| Avg response time | ~10s |
| Security level | Maximum |
| EER | 4.6% |
| AUC | 0.991 |
| Balanced accuracy | 94.7% |
| Avg response | ~10s |
/health
## Base URL
```
https://api.moveris.com
```
## Response Fields
/api/v1/fast-check-stream
## Base URL
```
https://api.moveris.com
```
## Basic Flow
```
1. Generate a session_id (UUID) for the verification session
2. Capture N video frames (N = model's frames_required, e.g. 10 for mixed-10-v2, 30 for mixed-30-v2)
3. Encode each frame as base64 PNG
4. Send each frame in a separate POST to /api/v1/fast-check-stream (same session_id, same model)
5. On the final frame, the API returns the verdict ("live" or "fake") with confidence score
```
!!! info "Stream vs single request"
Unlike `/api/v1/fast-check` (which sends all frames in one JSON body), this endpoint receives **one frame per POST**. Use the same `session_id` and `model` for all requests. The verdict is returned only in the response to the last frame.
/api/v1/fast-check
## Base URL
```
https://api.moveris.com
```
!!! info "Frame requirement"
The API requires at least the number of frames required by the selected model. Use 10 frames for `mixed-10-v2`, 30 for `mixed-30-v2`, 60 for `mixed-60-v2`, 90 for `mixed-90-v2`, or 120 for `mixed-120-v2`. If you send fewer, you will get `insufficient_frames`. For predictable latency, send exactly `frames_required`.
/api/v1/fast-check-crops
!!! info "Frame requirement"
The API requires at least the number of crops required by the selected model (e.g. 10 for `mixed-10-v2`, 30 for `mixed-30-v2`). Each crop must be 224×224 PNG. If you send fewer, you will get `insufficient_frames`. For predictable latency, send exactly `frames_required`. See [Models](../models/overview.md).
/api/v1/live-check
!!! info "v2 upload-first variant"
The same landmark requirements apply to `POST /api/v2/live-check` after uploading frames (with landmarks) via `POST /api/v2/upload`. See [V2 Upload-First Pipeline](v2-pipeline.md).
## Base URL
```
https://api.moveris.com
```
## Requirements
- **V3 models only** — e.g. `mixed-10-v3`, `mixed-30-v3_1`. Other aliases return `unsupported_model` (400).
- **Landmarks per frame** — ≥468 points in normalized `[0, 1]` coordinates. Accepts `[x, y, z]` arrays or `{x, y, z}` objects (MediaPipe JS format).
- **Frame count** — Must match the model minimum (e.g. 10 for `mixed-10-v3_1`).
## Basic Flow
```
1. Generate a session_id (UUID)
2. Capture N frames with MediaPipe Face Mesh landmarks attached to each frame
3. Encode pixels as base64 PNG
4. POST /api/v1/live-check with all frames in one request
5. Receive verdict ("live" or "fake") with real_score
```
## Request Headers
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| `X-API-Key` | string | Yes | Your API key |
| `X-Model-Version` | string | No | Version alias for v2 model resolution (e.g. `latest`) |
## Request body
/api/v2/upload
Buffering only. Stores frames (or extracts them from an uploaded video) keyed by `session_id`. **Never runs inference.**
### Request body
Provide **exactly one** of `frames` (JSON array) or `video` (multipart file).
/api/v2/fast-check
Runs inference on frames previously uploaded via `/api/v2/upload`. The request carries **no frame pixels** — only session metadata.
### Request body
/api/v2/live-check
Same as v2 fast-check, but requires V3 models and frames uploaded **with landmarks** during the upload step (set `withLandmarks: true` on `v2Upload`). See [Live Check](live-check.md) for landmark requirements.
---
## Model selection
Same v1 vs v2 resolution as other endpoints. See [Model Versioning & Frames](../models/versioning-and-frames.md).
| Flow | Header | Body |
|------|--------|------|
| **v1 (direct)** | — | `model: "mixed-30-v3_1"` |
| **v2 (header)** | `X-Model-Version: latest` | `frame_count: 30` |
---
## Idempotency
Reusing a `session_id` with a **different model** than the one that produced a cached verdict returns **409** with `session_model_mismatch`. See [Errors](errors.md#session-model-mismatch-409).
---
## Related
- [Live Check](live-check.md) — V3 landmark-based path (v1 batch and v2 upload-first)
- [Fast Check Stream](fast-check-stream.md) — v1 streaming alternative
- [LivenessClient — v2 methods](../sdk/shared/client.md#v2-upload-first-pipeline)
- [React Hooks — useLivenessV2](../sdk/react/hooks.md#uselivenessv2)
========================================================================
Source: api-reference/errors.md
URL: https://documentation.moveris.com/api-reference/errors/
========================================================================
# Error Responses
Understanding and handling API errors effectively.
!!! info "In plain terms"
When something goes wrong, the API returns a consistent JSON envelope with `success: false`, a human-readable `message`, and an `errors` array listing error codes and descriptions. Use the error code to decide what to do (e.g., prompt for a new API key, show a "low credits" message, or retry later).
## Standard Response Envelope
All API responses (success and error) use the same envelope format.
### Success (`2xx`)
```json
{
"data": { ... },
"success": true,
"message": "OK"
}
```
### Error (`4xx` / `5xx`)
```json
{
"data": null,
"success": false,
"message": "Human-readable summary of the error",
"errors": [
{ "error_code": ["Detailed error message"] }
]
}
```
insufficient_frames | Not enough frames provided | You sent fewer frames than the model requires. Frame count must meet the model minimum (e.g. 10 for mixed-10-v2, 30 for mixed-30-v2). |
| 400 | missing_field | Required field missing | A required field (e.g. `session_id`, `frames`) is missing from the request. |
| 401 | invalid_key | Invalid or missing API key | Your API key is wrong, expired, or not sent. Check the `X-API-Key` header. |
| 402 | insufficient_credits | Not enough credits | Your account has run out of credits. Top up in the Developer Portal. |
| 402 | account_suspended | Account suspended | Your account is suspended due to a payment issue. Update your payment method in the Developer Portal. |
| 403 | insufficient_scope | API key lacks required scope | Your API key does not have permission for this operation. Create a key with the required scope in the Developer Portal. |
| 400 | validation_error | Request validation failed | The request format is invalid (e.g. wrong field types, invalid UUID). Returned as `400` with field-level detail in `errors` (not `422`). |
| 409 | session_model_mismatch | Session model conflict | You reused a `session_id` with a different model than the one that produced the cached verdict. Generate a new `session_id` or use the same model. |
| 429 | rate_limit_exceeded | Too many requests | You've hit the request limit. Wait for `retry_after` seconds and try again. |
| 500 | internal_error | Server error | Something went wrong on our side. Retry later or check the Status Page. |
## Common Errors
### Insufficient Frames (400)
Returned when the number of submitted frames is less than the required minimum for the endpoint.
```json
{
"data": null,
"success": false,
"message": "Insufficient frames. Model \"10\" requires 10 frames, received 5.",
"errors": [
{ "insufficient_frames": ["Insufficient frames. Model \"10\" requires 10 frames, received 5."] }
]
}
```
### Session Model Mismatch (409) {: #session-model-mismatch-409 }
Returned when you reuse a `session_id` that already has a cached verdict but request a **different model**. The API rejects the replay instead of returning another model's result under the new alias.
```json
{
"data": null,
"success": false,
"message": "session_id was already processed with model \"mixed-10-v3_1\"; it cannot be reused with model \"mixed-30-v3_1\". Use a new session_id.",
"errors": [
{ "session_model_mismatch": ["session_id was already processed with model \"mixed-10-v3_1\"; it cannot be reused with model \"mixed-30-v3_1\". Use a new session_id."] }
]
}
```
For `fast-check-stream`, switching the model mid-session (after frames are buffered under another model) returns the same `session_model_mismatch` code with a streaming-specific message.
!!! tip "How to avoid this"
Generate a fresh `session_id` per verification attempt, or keep the same model for all requests in a session (including `fast-check-stream` frames). Cached responses report the **executed** model, not a requested alias that differed at replay time.
### Invalid API Key (401)
Returned when the API key is invalid or missing.
```json
{
"data": null,
"success": false,
"message": "Not authenticated",
"errors": [
{ "invalid_key": ["Not authenticated"] }
]
}
```
### Insufficient Credits (402)
Returned when your account doesn't have enough credits to process the request.
```json
{
"data": null,
"success": false,
"message": "Insufficient credits. Required: 1, available: 0",
"errors": [
{ "insufficient_credits": ["Insufficient credits. Required: 1, available: 0"] }
]
}
```
### Account Suspended (402)
Returned when your account is suspended due to a payment issue (e.g. failed payment, overdue invoice).
```json
{
"data": null,
"success": false,
"message": "Your account is suspended due to a payment issue. Please update your payment method.",
"errors": [
{ "account_suspended": ["Your account is suspended due to a payment issue. Please update your payment method."] }
]
}
```
### Validation Error (400)
Returned when the request body fails validation. The API converts 422 validation errors to 400 with field-level detail.
```json
{
"data": null,
"success": false,
"message": "session_id is required",
"errors": [
{ "session_id": ["session_id is required"] }
]
}
```
### Insufficient Scope (403)
Returned when your API key does not have the required scope for the requested endpoint.
```json
{
"data": null,
"success": false,
"message": "API key lacks required scope: detection:write",
"errors": [
{ "insufficient_scope": ["API key lacks required scope: detection:write"] }
]
}
```
### Rate Limit Exceeded (429)
Returned when you've exceeded the rate limit for your account.
```json
{
"data": null,
"success": false,
"message": "Rate limit exceeded. Please try again later.",
"errors": [
{ "rate_limit_exceeded": ["Rate limit exceeded. Please try again later."] }
]
}
```
## Handling Errors
1. Check `success` first — if `false`, the request failed
2. Read `message` for a human-readable summary
3. Iterate `errors` to find specific error codes (e.g. `insufficient_frames`, `invalid_key`)
4. Use the error code to decide your recovery action
5. For `insufficient_scope`, create a new API key with the required scope in the Developer Portal
6. For rate limits, implement exponential backoff
7. Implement retry logic for transient errors (500)
8. For persistent 500 errors, check our [Status Page](https://status.moveris.com/){ target="_blank" } for ongoing incidents
## Related
- [Health Check](health-check.md)
- [Video Detect (Async)](video-detect.md)
- [Fast Check Stream (Default)](fast-check-stream.md)
- [Fast Check (Legacy)](fast-check.md)
- [Fast Check Crops](fast-check-crops.md)
- [Rate Limits](rate-limits.md)
========================================================================
Source: api-reference/rate-limits.md
URL: https://documentation.moveris.com/api-reference/rate-limits/
========================================================================
# Rate Limits
Understanding API rate limits and how to handle rate limiting responses.
!!! info "In plain terms"
The API limits how many requests you can make per minute (240 for most endpoints). If you exceed this, you get a `429` response with `retry_after` telling you how many seconds to wait. This protects the service and ensures fair usage. Contact Moveris for higher limits if needed.
## Limits by Endpoint
| Endpoint | Rate Limit |
|----------|------------|
| `/api/v1/fast-check` | 240 requests/minute |
| `/api/v1/fast-check-stream` | 240 requests/minute |
| `/api/v1/fast-check-crops` | 240 requests/minute |
!!! info "Higher Limits Available"
If you need higher rate limits for your application, contact the Moveris team to discuss enterprise plans with custom limits.
## Rate Limit Exceeded Response
When you exceed the rate limit, you'll receive a `429` response:
```json
{
"data": null,
"success": false,
"message": "Rate limit exceeded",
"errors": [
{ "rate_limit_exceeded": ["Rate limit exceeded"] }
]
}
```
The response may also include a **`Retry-After`** HTTP header (seconds until you can retry). Prefer that header when present.
## Handling Rate Limits
1. **Read `Retry-After`** — When the server sends this header, wait that many seconds before retrying. If the body includes `errors`, treat it like other API errors (see [Errors](errors.md)).
2. **Implement exponential backoff** — Start with the `Retry-After` value (when present) and increase wait time for subsequent failures.
3. **Queue requests** — If you're making many requests, implement a queue to stay within limits.
4. **Use Fast Check for high volume** — The /fast-check endpoint has the highest rate limit (240/min) for high-volume scenarios.
## Best Practices
- Monitor your request rate and stay within published limits
- Use session IDs to batch frames rather than making separate requests
- Cache results when appropriate to avoid duplicate requests
- Check the [Status Page](https://status.moveris.com/){ target="_blank" } if you experience unexpected rate limiting or errors
## Related
- [Health Check](health-check.md)
- [Video Detect (Async)](video-detect.md)
- [Fast Check Stream (Default)](fast-check-stream.md)
- [Fast Check (Legacy)](fast-check.md)
- [Fast Check Crops](fast-check-crops.md)
- [Errors](errors.md)
========================================================================
Source: examples/javascript.md
URL: https://documentation.moveris.com/examples/javascript/
========================================================================
# JavaScript Examples {: .javascript-examples-page }
Complete JavaScript examples for integrating Moveris API (v2).
!!! info "In plain terms"
Copy these code snippets to add liveness detection to your web app. They show how to capture frames from a video element, send them to the API, and display the result. Frame count depends on the model (e.g. 10 for `mixed-10-v2`, 30 for `mixed-30-v2`). Replace the placeholder API key with yours (preferably via a backend proxy).
!!! info "Moveris API (v2)"
These examples use Moveris API (v2) at `https://api.moveris.com`
!!! tip "Model selection"
Examples use the v1 flow (`model` in body). For v2 resolution, send `X-Model-Version: latest` header with `frame_count: 10|30|60|90|120` in the body. See [Model Versioning & Frames](../models/versioning-and-frames.md).
## REST API Examples
=== "JavaScript"
```javascript
async function checkLiveness(videoElement) {
const frames = [];
// Capture frames at ~10 FPS (count = model min_frames, e.g. 10 for mixed-10-v2)
const frameCount = 10; // Use getModels() for dynamic model selection
for (let i = 0; i < frameCount; i++) {
const canvas = document.createElement('canvas');
canvas.width = 640;
canvas.height = 480;
const ctx = canvas.getContext('2d');
ctx.drawImage(videoElement, 0, 0, 640, 480);
frames.push({
index: i,
timestamp_ms: performance.now(),
pixels: canvas.toDataURL('image/png').split(',')[1]
});
// Wait ~100ms between frames (10 FPS)
await new Promise(r => setTimeout(r, 100));
}
const response = await fetch('https://api.moveris.com/api/v1/fast-check', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'sk-your-api-key'
},
body: JSON.stringify({
session_id: crypto.randomUUID(),
source: 'live',
model: 'mixed-10-v2',
frames: frames
})
});
const body = await response.json();
if (!body.success) {
throw new Error(body.message ?? 'Request failed');
}
return body.data;
}
```
=== "TypeScript"
```typescript
interface Frame {
index: number;
timestamp_ms: number;
pixels: string; // Base64
}
interface LivenessResult {
verdict: "live" | "fake";
real_score: number;
score: number;
session_id: string;
processing_ms: number;
}
async function checkLiveness(
frames: Frame[],
sessionId: string
): Promise{eyeFeedback}
} {feedback &&{feedback}
}Frames: {progress.current}/{progress.total}
{state === 'idle' && } ); } ``` !!! tip "SDK options" - `captureIntervalMs` (default 100) — desired minimum ms between captures (e.g. 50 for ~20 FPS) - `minCaptureDelay` (default 300) — hard floor between captures; set closer to `captureIntervalMs` so the interval is not capped by the default floor - `onEyeWarning` — called with messages like "Eyes are in shadow" or "Glare detected" before `onRestartNeeded` - After frames are collected, the SDK stops the camera while the API request runs (`uploading`); see [React hooks](../sdk/react/hooks.md#usesmartframecapture) !!! info "Adaptive quality gates (3.19+ / platform-aware 3.22+)" `useSmartFrameCapture` adapts blur and brightness thresholds to each user's camera, lighting, and platform automatically. You can still pass `blurThreshold` and `brightnessThreshold` as **floors** (minimum values), not fixed cutoffs. A blur rejection resets the frame buffer so V3+ models receive consecutive frames — guide the user to hold still after a dropout. See the [Changelog](../changelog.md) entries for **2.9.0** and **2.13.0**. ## Installation ```bash # Install MediaPipe for face detection (optional, for crops) npm install @mediapipe/tasks-vision ``` ## Usage Tips - **Cleanup streams:** Always stop camera tracks in the useEffect cleanup to prevent memory leaks. - **Face guide overlay:** Add a visual guide to help users position their face correctly within the frame. - **Loading states:** Disable the button and show progress during verification to prevent double-submissions. - **Error boundaries:** Wrap the camera component in an error boundary to gracefully handle permission denials. - **Mobile considerations:** Use `playsInline` and `muted` attributes for iOS compatibility. ======================================================================== Source: examples/react-native.md URL: https://documentation.moveris.com/examples/react-native/ ======================================================================== # React Native Examples Mobile integration examples for React Native apps using Expo Camera and React Native Vision Camera. !!! info "In plain terms" These examples show how to add liveness detection to mobile apps (iOS and Android) using the device camera. Use Expo Camera for simpler setups or React Native Vision Camera for more control. Always proxy API calls through your backend to protect the API key. !!! info "Moveris API (v2)" These examples use Moveris API (v2) endpoints. The `source` field is required and should be set to `"live"` for real-time camera capture. !!! warning "Backend Proxy Required" Never include your API key in mobile app code. Always route requests through your backend server to keep credentials secure. !!! tip "Model selection (v1 and v2)" You can keep both flows depending on your integration. Use `model` in body for v1 compatibility, or use `X-Model-Version: latest` with `frame_count` for v2 alias-based resolution. ## Expo Camera The easiest way to add liveness detection to Expo projects. Expo Camera provides built-in base64 encoding, making frame capture straightforward. ```typescript import { CameraView, useCameraPermissions } from 'expo-camera'; import { useRef, useState } from 'react'; import { Button, View, Text, StyleSheet, ActivityIndicator } from 'react-native'; interface Frame { index: number; timestamp_ms: number; pixels: string; } interface LivenessResult { verdict: 'live' | 'fake'; real_score: number; score: number; session_id: string; } export default function LivenessScreen() { const [permission, requestPermission] = useCameraPermissions(); const [isChecking, setIsChecking] = useState(false); const [result, setResult] = useStategetModels() | `/api/v1/models` | -- | Fetch available models (id, label, min_frames, deprecated) |
| fastCheck() | `/api/v1/fast-check` | by model | Fast liveness check with server-side face detection |
| fastCheckCrops() | `/api/v1/fast-check-crops` | by model | Fast check with pre-cropped 224x224 face images |
| fastCheckStream() | `/api/v1/fast-check-stream` | by model | Parallel frame streaming for lowest latency |
| liveCheck() | `/api/v1/live-check` | by model | V3 batch with client-supplied MediaPipe landmarks |
| v2Upload() | `/api/v2/upload` | chunks | Buffer frames during capture (v2 pipeline) |
| v2FastCheck() | `/api/v2/fast-check` | — | Inference by `session_id` after v2 upload |
| v2LiveCheck() | `/api/v2/live-check` | — | V3 live-check variant after v2 upload with landmarks |
| verify() | `/api/v1/verify` | 50+ | Spatial-feature analysis for standard KYC |
| hybridCheck() | `/api/v1/hybrid-check` | 50+ | CNN + physiological hybrid model |
| hybrid50() | `/api/v1/hybrid-50` | 50+ | 50-frame hybrid (93.8% accuracy) |
| hybrid150() | `/api/v1/hybrid-150` | 150+ | 150-frame hybrid (96.2% accuracy) |
| health() | `/health` | -- | Health check |
## Protocol
The SDK communicates with the Moveris API over **HTTPS REST** with JSON payloads. Authentication is via the `X-API-Key` header. All requests include automatic retry with exponential backoff (3 attempts, 1s--10s delays).
## Next Steps
- [Installation](installation.md) -- Install the SDK packages
- [WebRTC Quick Start](webrtc/quick-start.md) -- Observer-based WebRTC transport with `@moveris/webrtc`
- [Cognito Check Quick Start](cognito-check/quick-start.md) -- Integrate the framework-agnostic embeddable widget
- [Cognito Check React Quick Start](cognito-check-react/quick-start.md) -- Integrate the React wrapper for the embeddable widget
- [React Quick Start](react/quick-start.md) -- Get started with React in 5 minutes
- [React Native Quick Start](react-native/quick-start.md) -- Get started with React Native
- [LivenessClient Reference](shared/client.md) -- Full API client documentation
========================================================================
Source: sdk/installation.md
URL: https://documentation.moveris.com/sdk/installation/
========================================================================
# Installation {: .installation-page }
Install the SDK package for your platform. All packages are published to npm under the `@moveris` scope.
!!! info "In plain terms"
Run the install command for your platform (React web, [React Native](../glossary.md#react-native)). For React, you need `@moveris/react` and `@moveris/shared`. For React Native, add `@moveris/react-native` instead. Optional: install `@mediapipe/tasks-vision` for client-side face detection.
## React (Web)
```bash
npm install @moveris/react @moveris/shared
```
Or with other package managers:
=== "pnpm"
```bash
pnpm add @moveris/react @moveris/shared
```
=== "yarn"
```bash
yarn add @moveris/react @moveris/shared
```
### Peer Dependencies
| Package | Required Version |
|---|---|
| `react` | >= 18.0.0 |
| `react-dom` | >= 18.0.0 |
### Optional Dependencies
For client-side face detection (used by `useFaceDetection` and `useSmartFrameCapture`):
```bash
npm install @mediapipe/tasks-vision
```
## React Native
```bash
npm install @moveris/react-native @moveris/shared
```
### Peer Dependencies
| Package | Required Version |
|---|---|
| `react` | >= 18.0.0 |
| `react-native` | >= 0.83.1 |
| `react-native-vision-camera` | ^4.0.0 |
| `react-native-reanimated` | ^3.15.0 |
Install the peer dependencies:
```bash
npm install react-native-vision-camera react-native-reanimated
```
For iOS, install native pods:
```bash
cd ios && pod install
```
### Platform Configuration
#### iOS (`Info.plist`)
```xml
Status: {status}
Frames: {framesReceived}/{framesRequired}
{status === 'idle' && ( )} {result && (Verdict: {result.verdict}
Score: {(result.realScore).toFixed(0)}
)} {error &&Error: {error.message}
} ); } ``` ## With Face Detection Enable smart frame capture that only captures frames when a face is properly positioned: ```tsx import { MoverisProvider, LivenessView, createMediaPipeAdapter, } from '@moveris/react'; function App() { return ("searching" |"aligning" |"ready" | "capturing" | `"searching"` | Oval guide visual state |
| `feedbackMessage` | `string` | -- | Message displayed below the oval |
| `style` | `CSSProperties` | -- | Overlay style overrides |
---
## LivenessButton
Styled action button for start, stop, and retry actions.
```tsx
"primary" |"secondary" |"danger" | `"primary"` | Visual style |
| `disabled` | `boolean` | `false` | Disable the button |
| `loading` | `boolean` | `false` | Show loading spinner |
---
## LivenessResult
Displays the verification result with verdict, score, and `realScore` (use for decision-making).
```tsx
{feedbackMessage}
} {status === 'capturing' &&{framesReceived}/{framesRequired}
} {status === 'processing' &&Analyzing...
} {result &&Verdict: {result.verdict}
} {error &&Error: {error.message}
} {(result || error) && } ); } ``` --- ## useLivenessV2 Self-contained hook for the **v2 upload-first pipeline**. Uploads frames in chunks during capture (`POST /api/v2/upload`), then runs a single `POST /api/v2/fast-check` or `POST /api/v2/live-check` when capture completes. Completely separate from `useLiveness` (v1). ```typescript const { state, result, error, progress, start, stop, reset, captureFrame, } = useLivenessV2(options?); ``` ### Options