API Reference
REST API for face verification, liveness detection, and live monitoring.
1. Authentication
All requests require an X-API-Key header. Get your key from the Dashboard.
curl https://verify.merilive.com/api/public/v1/verify-face \
-H "X-API-Key: fv_live_..." \
-H "Content-Type: application/json" \
-d '{"external_user_id":"u_123","image_base64":"..."}'2. Verify Face
https://verify.merilive.com/api/public/v1/verify-faceRuns face detection + liveness + duplicate scan via the MeriCore dual-engine.
Request body
{
"external_user_id": "your_user_id",
"image_base64": "<base64-encoded JPEG>",
"metadata": { "any": "context" }
}Response
{
"verification_id": "uuid",
"status": "approved" | "needs_review" | "rejected" | "duplicate",
"confidence": 98.4,
"liveness_passed": true,
"gender": "female",
"engine_agreement": "both_passed"
}3. Live Monitoring
https://verify.merilive.com/api/public/v1/monitor-frameReal-time frame analysis. Detects sleeping, face-lost, and looking-away conditions. Call once per second during a live stream.
Response
{
"face_present": true,
"eyes_open": false,
"looking_forward": true,
"alerts": ["sleep_detected"]
}4. Get Verification
https://verify.merilive.com/api/public/v1/verification/{id}Fetch full details for a previously created verification.
5. Content Moderation (Chat / Comments)
https://verify.merilive.com/api/public/v1/scan-contentScans any text (chat message, comment, profile bio) for hate speech, harassment, sexual content, threats, and self-harm. Combines OpenAI Moderation, Lovable AI (Gemini 2.5 Flash), your custom keyword blocklist, and a South Asian hate-speech lexicon (Bangla, Hindi, Urdu, Arabic). Worst-of-four verdict.
Request body
{
"text": "the message to scan",
"external_user_id": "u_123"
}Response
{
"verdict": "allow" | "review" | "block",
"categories": ["hate_speech", "insult"],
"score": 0.92,
"sources": {
"openai": { ... },
"lovable_ai": { ... },
"custom_keywords": [...],
"hate_lexicon": [...]
}
}Note: This endpoint uses Lovable AI (Gemini 2.5 Flash) for nuanced multilingual moderation. Each scan consumes a small amount of workspace AI credit on top of your MeriCore request quota. Manage your custom blocklist words per API key from Admin → API Keys.
6. Index Face (Duplicate Account Prevention)
https://verify.merilive.com/api/public/v1/index-faceIndexes a user's selfie into your tenant's AWS Rekognition collection. Call this once per user during signup. The face vector is stored and later matched by /search-face to block duplicate signups.
Request body
{
"external_user_id": "u_123",
"image_base64": "<base64-encoded JPEG>",
"metadata": { "any": "context" }
}Response
{
"status": "indexed",
"face_id": "aws-rekognition-face-id",
"external_user_id": "u_123",
"collection_id": "fv_<tenant>",
"confidence": 99.8
}7. Search Face (Find Duplicates)
https://verify.merilive.com/api/public/v1/search-faceSearches your tenant's face index for selfies similar to the supplied image. Returns all matches above the similarity threshold so you can detect users trying to open a second account. Default threshold (configurable per API key from Admin → API Keys) is 95%.
Request body
{
"image_base64": "<base64-encoded JPEG>",
"threshold": 95,
"max_matches": 10
}Response
{
"matches": [
{
"external_user_id": "u_123",
"similarity": 99.4,
"face_id": "...",
"indexed_at": "2026-05-23T..."
}
],
"is_duplicate": true,
"threshold_used": 95
}Flagged duplicates are listed in Admin → Duplicate Accounts.
8. Verify Document (OCR + Tamper + Face Match)
https://verify.merilive.com/api/public/v1/verify-documentOCR + tamper detection + ID-photo vs selfie face match for Aadhaar, PAN, Passport (MRZ), NID, Driving License. Powered by AWS Textract, Rekognition CompareFaces, and Gemini vision.
Request body
{
"external_user_id": "u_123",
"document_image_base64": "<base64 JPEG of ID>",
"selfie_image_base64": "<base64 JPEG of selfie>"
}Response
{
"verification_id": "uuid",
"status": "approved" | "needs_review" | "rejected",
"document_type": "passport" | "aadhaar" | "pan" | "nid" | "driving_license",
"name": "...", "dob": "1990-01-01", "id_number": "...", "expiry": "2030-01-01",
"nationality": "IND", "gender": "M",
"face_match_score": 96.4, "face_match_passed": true,
"tamper_score": 0.08, "tamper_passed": true, "tamper_signals": [],
"mrz": { "format": "TD3", "...": "..." },
"reasons": []
}9. Webhooks
Receive real-time events instead of polling. Configure a webhook URL per API key in the admin dashboard. We POST signed JSON when subscribed events fire, with automatic retries (5 attempts, exponential backoff: 30s → 2m → 10m → 1h → 6h).
Events
| Event | Fires when |
|---|---|
| verification.completed | verify-face or verify-document succeeds (approved / needs_review) |
| verification.failed | verify-face or verify-document is rejected |
| frame.flagged | monitor-frame detects sleep / face-lost / looking-away |
| content.blocked | scan-content blocks chat / comment (profanity, keywords, age) |
| duplicate.detected | search-face matches an existing identity above the threshold |
Request headers
POST <your-webhook-url>
Content-Type: application/json
X-MeriCore-Event: verification.completed
X-MeriCore-Signature: sha256=<hex digest>
X-MeriCore-Delivery: <delivery-uuid>
X-MeriCore-Attempt: 1Payload shape
{
"id": "<event-uuid>",
"event": "verification.completed",
"created_at": "2026-05-23T18:00:00.000Z",
"api_key_id": "<your-key-uuid>",
"data": { /* event-specific — see your endpoint's response shape */ }
}Verify signature — Node.js
import crypto from "crypto";
app.post("/hooks/mericore", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.header("X-MeriCore-Signature") || "";
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.MERICORE_WEBHOOK_SECRET)
.update(req.body) // raw Buffer
.digest("hex");
const ok =
sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.status(401).send("bad signature");
const event = JSON.parse(req.body.toString());
// handle event.event / event.data
res.sendStatus(200);
});Verify signature — Python
import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["MERICORE_WEBHOOK_SECRET"].encode()
@app.post("/hooks/mericore")
def hook():
raw = request.get_data() # raw bytes — do NOT use request.json
sig = request.headers.get("X-MeriCore-Signature", "")
expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401)
event = request.get_json()
# handle event["event"] / event["data"]
return "", 200Delivery rules
- Respond with any
2xxwithin 10s to acknowledge. - Any non-2xx, timeout, or network error triggers a retry.
- After 5 failed attempts the delivery is marked
dead. - Manually replay any delivery from
/admin/webhooks. - Always verify the signature against the raw request body — JSON re-serialization will break it.
10. Code Examples
Node.js
const res = await fetch("https://verify.merilive.com/api/public/v1/verify-face", {
method: "POST",
headers: {
"X-API-Key": process.env.MERICORE_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
external_user_id: "u_123",
image_base64: imageBuffer.toString("base64"),
}),
});
const data = await res.json();
console.log(data.status); // "approved" | "needs_review" | ...Python
import base64, requests, os
with open("face.jpg", "rb") as f:
img = base64.b64encode(f.read()).decode()
r = requests.post(
"https://verify.merilive.com/api/public/v1/verify-face",
headers={"X-API-Key": os.environ["MERICORE_KEY"]},
json={"external_user_id": "u_123", "image_base64": img},
)
print(r.json()["status"])11. Compliance & GDPR/DPDP
MeriCore is GDPR (EU) and DPDP Act 2023 (India) compliant. Every API request is audit-logged with IP + user-agent. The following endpoints implement Subject Access, Right to Erasure, and Consent.
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v1/user/:id/data | GDPR Art. 15 — export all user data as JSON |
| DELETE | /v1/user/:id | GDPR Art. 17 — right to be forgotten |
| POST | /v1/user/:id/consent | DPDP Act — record consent grant/revoke |
| GET | /v1/user/:id/consent | Retrieve consent history |
# Record user consent (DPDP Act)
curl -X POST https://verify.merilive.com/api/public/v1/user/u_123/consent \
-H "X-API-Key: $MERICORE_KEY" \
-H "Content-Type: application/json" \
-d '{"purpose":"face_verification","granted":true,"policy_version":"v1.0"}'
# Export user data (GDPR SAR)
curl https://verify.merilive.com/api/public/v1/user/u_123/data \
-H "X-API-Key: $MERICORE_KEY"
# Delete user (GDPR Right to Erasure)
curl -X DELETE https://verify.merilive.com/api/public/v1/user/u_123 \
-H "X-API-Key: $MERICORE_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"user_requested"}'Security posture: All data encrypted at rest with AES-256 (managed by Lovable Cloud). TLS 1.3 in transit. Row-Level Security on every user-data table. Face embeddings stored as mathematical vectors (not raw biometric images). Every API request captured to an immutable audit log with IP + user-agent for SOC 2 Type 2 and ISO 27001 evidence. Deletion and export requests are logged immutably even after the underlying data is purged.
12. Error Codes
| Code | Meaning |
|---|---|
| 401 | Missing or invalid X-API-Key |
| 402 | Insufficient credits — top up your balance |
| 403 | API key revoked or suspended |
| 400 | Invalid request body or unsupported image |
| 429 | Rate limit exceeded (10 req/sec per key) |
| 500 | Internal error — please retry |