Skip to content

Meeting Liveness BotIntegration Guide

This guide walks through a production backend integration: credentials, session management, webhook handling, and the optional interviewer view.

In plain terms

Your server starts the bot before an interview, stores the session ID, and listens for webhook notifications when each participant is checked. You can also give an interviewer a link to watch results live—without building your own UI.

Before You Start

What You Need From Moveris

Bot API key

sk-bot-<key> — authenticates POST /api/sessions and related M2M routes.

Moveris API key (analysis)

Used by the hosted bot for POST /api/v1/fast-check. Moveris configures this on the bot service for your organization.

Bot base URL

Public URL of your environment (for example https://meet.example.com).

Webhook on the same API key

Register your HTTPS endpoint in the Developer Portal for the same Moveris API key the bot uses for analysis.

Deliverable Description
Bot API key Prefixed with sk-bot-. Your backend sends it on every bot API call.
Moveris API key Powers liveness analysis. Must match the key that owns your webhook configuration.
Bot base URL Where your backend calls /api/sessions.
Org branding (optional) Display name and logo when the bot joins a meeting.

Contact the Moveris team for key provisioning, bot URL, org branding, and webhook setup.

What You Build

Component Responsibility
Session orchestrator Calls POST /api/sessions when a meeting is scheduled or starts
Webhook receiver HTTPS POST endpoint; verifies X-Webhook-Signature; handles verification.completed
Correlation store Maps bot sessionId, participant IDs, and webhook session_id
Interviewer delivery (optional) Sends /interview/<interviewToken> to human observers

One API key for analysis and webhooks

The bot calls fast-check with your org’s Moveris API key. Webhooks fire on that same key. Register the webhook in the Developer Portal on the key Moveris assigns to your bot deployment—not a separate test key unless Moveris configures it that way.


Authentication

All backend requests to the bot use:

Authorization: Bearer sk-bot-<your-bot-key>
Content-Type: application/json

No browser login or session cookie is required for M2M integration.

The bot validates your key against the Moveris Developer Portal API and loads organization branding for the meeting.

sequenceDiagram
    participant BE as Your backend
    participant Bot as Meeting Liveness Bot
    participant API as Moveris API

    BE->>Bot: Authorization: Bearer sk-bot-*
    Bot->>API: POST /api/auth/v1/org-bot-keys/validate/ body key
    API-->>Bot: success envelope + org branding
    Bot-->>BE: 200 session created or 401

Validate request (called by the bot, not your backend):

POST https://<moveris-api-url>/api/auth/v1/org-bot-keys/validate/
Content-Type: application/json

{ "key": "sk-bot-<your-bot-key>" }

Success (standard Moveris API envelope):

{
  "data": {
    "organization_id": 42,
    "organization_name": "Your Organization",
    "organization_slug": "your-org",
    "bot_display_name": "Liveness Verifier",
    "logo_url": "https://example.com/logo.png",
    "primary_color": "#0066ff"
  },
  "success": true,
  "message": "OK"
}

Keep keys on the server

Never expose the bot API key or Moveris API key in client-side code, mobile apps, or public repositories.


End-to-End Flow

sequenceDiagram
    participant Backend as Your backend
    participant Bot as Meeting Liveness Bot
    participant Provider as Meeting provider
    participant Moveris as Moveris API
    participant Webhook as Your webhook endpoint
    participant Observer as Interviewer (optional)

    Backend->>Bot: POST /api/sessions + Bearer sk-bot-*
    Bot->>Provider: Create bot for meeting URL
    Bot-->>Backend: sessionId, interviewToken
    Backend->>Observer: Share /interview/token (optional)
    Provider->>Bot: WebSocket video frames
    Bot->>Moveris: POST /api/v1/fast-check per participant
    Moveris->>Webhook: verification.completed
    Backend->>Backend: Correlate session_id to participant

Integration timeline

flowchart TB
    S1[1. Schedule / start meeting] --> S2[2. POST /api/sessions]
    S2 --> S3[3. Store sessionId + interviewToken]
    S3 --> S4[4. Share /interview/token optional]
    S4 --> S5[5. Bot joins call]
    S5 --> S6[6. Webhook verification.completed per participant]
    S6 --> S7[7. Interviewer sees SSE updates optional]
    S7 --> S8[8. Meeting ends or DELETE session]
Step Action
1 Your workflow schedules or starts the video meeting
2 Backend calls POST /api/sessions with meetingUrl and optional model
3 Persist sessionId and interviewToken if using the interviewer view
4 Send https://<bot-url>/interview/<interviewToken> to observers (optional)
5 Bot joins automatically (may wait in a lobby)
6 Your webhook receives verification.completed for each analyzed participant
7 Observer watches live verdicts in the browser (optional)
8 Meeting ends naturally, or call DELETE /api/sessions/:id early

See How It Works for the difference between bot status (SSE) and verdict webhooks.


Creating a Session

Request

POST https://<bot-url>/api/sessions
Authorization: Bearer sk-bot-<your-bot-key>
Content-Type: application/json
{
  "meetingUrl": "https://meet.google.com/abc-defg-hij",
  "model": "mixed-10-v3_1"
}
Field Type Required Description
meetingUrl string Yes Google Meet, Zoom, or Microsoft Teams meeting URL
model string No Mixed model alias (default mixed-10-v2 if omitted)
targetParticipantNames string[] No If set, scan only participants whose names match. See Targeted participant scanning
excludeParticipantNames string[] No Names to skip — useful for excluding interviewers or hosts
bgSegmentation boolean No Replace backgrounds with neutral grey before analysis. Defaults to the Moveris deployment setting. See Background segmentation
faceGate boolean No Enable face geometry / pose checks in the quality gate. Defaults to the Moveris deployment setting. See Frame quality gating

Hosted service

The bot is hosted and configured by Moveris, so the meeting provider can stream frames back automatically. You do not pass any callback URL—just meetingUrl and an optional model.

Response

{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "botId": "bot_abc123",
  "status": "bot_created",
  "interviewToken": "eyJzZXNzaW9uSWQiOiI1NTBlODQwMC4uLiJ9.abc123sig",
  "message": "Bot is being created and will join the meeting shortly"
}
Field Description
sessionId Bot session ID — store this; used to correlate webhooks and optional polling
botId Meeting provider’s bot identifier for this session
interviewToken Signed token for the read-only interviewer view (24-hour TTL)
status Initial bot state — see Session Lifecycle

Model selection

The bot passes your model to POST /api/v1/fast-check with source: "live". Frame count follows the model alias (for example 10 frames for mixed-10-v3_1_1).

Generation Example aliases When to use
V3.1.1 (recommended) 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 New integrations
V3.1 mixed-10-v3_1, mixed-30-v3_1, mixed-60-v3_1, mixed-90-v3_1 Deployments pinned to V3.1
V3 mixed-10-v3, mixed-30-v3, mixed-60-v3 Deployments pinned to V3
V2 mixed-10-v2mixed-120-v2 Legacy or explicit V2 requirement

Full comparison: Overview — Models · Model Versioning & Frames


Targeted Participant Scanning

By default the bot scans every participant it sees on camera. Pass targetParticipantNames to scan only specific people, and excludeParticipantNames to skip others.

In plain terms

In an interview you usually want to verify the candidate, not the interviewer. Give the bot the candidate's name and it checks only them.

How matching works

The bot matches a participant's display name against your list in two tiers:

  1. Fuzzy match — handles typos, reordered names, and partial names. A close match resolves immediately with no extra calls.
  2. LLM confirmation (optional) — for borderline cases, a fast LLM yes/no check decides. Moveris enables this step on the bot deployment; you don't configure it.

excludeParticipantNames uses the same matching but rejects matches — put interviewer or host names there so they are never scanned.

Request example

Scan only the candidate, skip the interviewer:

{
  "meetingUrl": "https://meet.google.com/abc-defg-hij",
  "model": "mixed-10-v3_1",
  "targetParticipantNames": ["John Smith"],
  "excludeParticipantNames": ["Jane Doe"]
}

When a participant is matched, the bot pins their video feed and waits for them to speak before collecting frames. This ensures frames capture the person's live face rather than an idle thumbnail.

Participant stages

In targeted mode each matched participant moves through these stages, surfaced on the session SSE stream:

Stage Meaning
matched Name matched; waiting for the participant to start speaking
accumulating Collecting frames during active speech
analyzing Frames submitted to the Moveris API
done Verdict available

Verdicts are still delivered through your verification.completed webhook with the same correlation rules.


Frame Quality Gating

Before a frame enters the accumulator, the bot evaluates it for capture quality. A rejected frame resets that participant's buffer so the liveness model still receives consecutive frames.

In plain terms

If the video is blurry, dark, or the face is missing or poorly framed, the bot discards the bad frame and starts collecting again. Your UI can show a short tip from the SSE event instead of waiting for a weak verdict.

What is checked

Checks Always on Needs face gate
Blur, too-dark, too-bright Yes
No face, multiple faces, size, margins, centering, backlit, head pose (yaw / pitch / roll) Yes (faceGate: true or deployment default)

Face checks load after a short model warmup. Until then, only blur and brightness run.

SSE event

Rejected frames emit frame-quality-rejected on the session events stream (throttled to about once per second per participant):

{
  "participantId": "p1",
  "participantName": "John Smith",
  "reason": "too-blurry",
  "framesCollected": 0,
  "framesRequired": 10
}

Use reason to show interviewer guidance. Configure face checks with Moveris or pass faceGate on session create when your deployment allows it.


Background Segmentation

Optional background segmentation replaces each participant's background with neutral grey before frames go to POST /api/v1/fast-check.

In plain terms

Busy or branded meeting backgrounds can distract the model. Turning this on keeps the face and replaces everything else with a plain grey backdrop.

Pass bgSegmentation: true (or false) on POST /api/sessions. If omitted, the bot uses the deployment default from Moveris. When enabled, the analysis request includes bg_segmentation: true (same field documented on Fast Check Crops).


Receiving Results via Webhook

Configure your webhook in the Developer Portal on the same Moveris API key the bot uses. Subscribe to verification.completed (and optionally verification.failed).

After each participant analysis, Moveris sends an HTTP POST to your registered URL. This uses the same delivery format as the REST API—not a separate bot-specific event name.

Headers

Header Description
Content-Type application/json
User-Agent Moveris-Webhook/1.0
X-Webhook-Event verification.completed or verification.failed
X-Webhook-Session Moveris analysis session ID (see correlation below)
X-Webhook-Signature sha256=<hmac_hex> — HMAC-SHA256 of the raw body

Payload (verification.completed)

{
  "event": "verification.completed",
  "session_id": "a3f7c291-8b2e-5c1d-9f0a-1b2c3d4e5f6a",
  "timestamp": "2026-06-01T15:26:42.123456Z",
  "data": {
    "verdict": "live",
    "real_score": 0.88,
    "score": 88.0,
    "confidence": 0.93,
    "type": "VERY HIGH",
    "session_id": "a3f7c291-8b2e-5c1d-9f0a-1b2c3d4e5f6a",
    "model": "mixed-10-v3_1",
    "input_source": "live",
    "processing_ms": 1240,
    "frames_processed": 10,
    "tenant_metadata": {
      "participant_id": "p1",
      "participant_name": "John Doe",
      "bot_session_id": "<parent_session_id>"
    },
    "warning": null,
    "created_at": "2026-06-01T15:26:42.123456Z",
    "frames": [
      "https://storage.example.com/frames/.../frame-0.png?token=..."
    ]
  }
}
Field Description
event Always verification.completed for a finished analysis
session_id Moveris analysis session ID — deterministic per bot session + participant (see below)
timestamp ISO-8601 time of the event
data.verdict "live" or "fake"
data.score Liveness score 0–100
data.real_score Normalized score 0.0–1.0
data.confidence Confidence 0.0–1.0
data.model Model alias used for this analysis
data.input_source "live" for meeting bot captures
data.processing_ms Analysis duration in milliseconds
data.frames_processed Number of frames analyzed
data.frames Presigned frame URLs when retention is enabled; empty array otherwise

Not wrapped in the API envelope

Webhook bodies are sent directly by the delivery service. They are not wrapped in { data, success, message } like REST API responses. See the Webhook Setup Guide for signature verification and failed-event examples.

Frame retention

data.frames is populated only when frame retention is enabled for your organization. URLs expire per your retention policy (typically a few minutes).

Correlating Webhooks to Participants

The bot assigns each participant a deterministic Moveris session ID before calling fast-check:

namespace  = "5e8cf7e0-e4c4-4b3a-8d3a-2f1c3b4a5e6f"
moveris_session_id = uuid_v5(namespace, "<botSessionId>-<participantId>")
Value Source
botSessionId sessionId from POST /api/sessions
participantId ID from the meeting provider for that person
Webhook session_id Equals moveris_session_id for that participant
flowchart LR
    A["POST /api/sessions → sessionId"] --> C["uuid_v5(namespace, sessionId + '-' + participantId)"]
    B["participantId from meeting"] --> C
    C --> D["Webhook session_id"]

The webhook payload does not include participant_id or participant_name. Use one of these patterns:

Pattern When to use
Precompute You already know participant IDs — compute uuid_v5 and match incoming session_id
Poll session results Call GET /api/sessions/<sessionId> and match results[participantId].moverisSessionId to the webhook session_id
Single participant One expected participant — one webhook maps to that person

Camera re-scan

If a participant toggles their camera off and on, the bot may send another analysis and webhook with a new session_id for the same person only if participant IDs change. Treat the latest verdict per your business rules; see Session Lifecycle.

Example (Python)

import uuid

NAMESPACE = uuid.UUID("5e8cf7e0-e4c4-4b3a-8d3a-2f1c3b4a5e6f")

def moveris_session_id(bot_session_id: str, participant_id: str) -> str:
    return str(uuid.uuid5(NAMESPACE, f"{bot_session_id}-{participant_id}"))

def find_participant_for_webhook(bot_session_id: str, webhook_session_id: str, participant_ids: list[str]) -> str | None:
    for pid in participant_ids:
        if moveris_session_id(bot_session_id, pid) == webhook_session_id:
            return pid
    return None

Webhook Security

Verify X-Webhook-Signature with your webhook secret. See Webhook Setup Guide — Verifying the Signature.


Optional: Poll Session Results

If you need participant names or IDs alongside webhooks, poll while the meeting is active:

GET https://<bot-url>/api/sessions/<sessionId>
Authorization: Bearer sk-bot-<your-bot-key>

The response includes results keyed by participantId, each with verdict, score, moverisSessionId, and related fields. Use this to build your correlation table or to backfill if a webhook was missed.


Optional: Manual Re-scan

Trigger a new analysis for one or all participants (same session, bot still in call):

POST https://<bot-url>/api/sessions/<sessionId>/retry/<participantId>
POST https://<bot-url>/api/sessions/<sessionId>/retry-all
Authorization: Bearer sk-bot-<your-bot-key>

Each successful re-scan can produce another verification.completed webhook with the same correlation rules.


Interviewer View

The interviewToken enables a read-only live dashboard—no bot API key or Google login.

URL Format

https://<bot-url>/interview/<interviewToken>

What the Page Does

  1. Validates the token via GET /api/interview/<token>
  2. Opens SSE at GET /api/interview/<token>/events
  3. Shows participants and verdicts as analysis completes

The token expires 24 hours after creation.

Typical Usage

  1. Your backend creates a session before the interview.
  2. Extract interviewToken from the response.
  3. Send the interview URL to the observer.
  4. They open it during the call and monitor results in real time.

Stopping a Session

DELETE https://<bot-url>/api/sessions/<sessionId>
Authorization: Bearer sk-bot-<your-bot-key>

Response

{
  "status": "stopped"
}

Error Handling

Bot API errors

{
  "error": "Human-readable error message"
}
HTTP Status Meaning
400 Missing or invalid meetingUrl
401 Invalid or revoked bot API key (Invalid bot key)
404 Session not found
500 Internal error — contact Moveris with sessionId and timestamp

Analysis failures

If fast-check fails after validation, you may receive verification.failed instead of verification.completed. The payload includes data.error and no verdict. Subscribe to both events in the Developer Portal if you need operational alerts.


Slack Notifications

When enabled on your bot deployment, Moveris can post formatted liveness verdicts to a Slack channel after each participant check.

In plain terms

This is an optional operator alert channel—not a replacement for your production webhook. Moveris configures it on the bot service when your team requests Slack visibility during pilots or ongoing monitoring.

Each message includes:

  • Environment label (for example Development, Staging, Production)
  • Participant name and verdict (Live, Fake, Inconclusive, or Error)
  • Score, model, processing time, and Moveris session_id
  • Meeting URL when available

Your backend integration should still rely on verification.completed webhooks for pass/fail decisions. See How It Works — Two Ways You Receive Updates. Contact the Moveris team to enable Slack alerts on your deployment.


Production Checklist

  • [ ] Bot API key stored in server-side secrets
  • [ ] Moveris API key and webhook registered on the same Developer Portal key (configured by Moveris on the bot)
  • [ ] Webhook URL is HTTPS and publicly reachable
  • [ ] Signature verification implemented (X-Webhook-Signature)
  • [ ] Subscribed to verification.completed (and verification.failed if needed)
  • [ ] Correlation tested: sessionId + participantId → webhook session_id
  • [ ] Model chosen (V3.1 recommended for new integrations)
  • [ ] Interviewer link flow tested (if used)
  • [ ] DELETE /api/sessions/:id tested for early termination
  • [ ] Re-scan behavior understood if participants toggle cameras

Contact

For bot API key provisioning, webhook configuration, bot URL, or integration support, contact the Moveris team.