Face recognition API powered by CloudFace Vision Engine™. Detect, index, and search faces across photo collections with a simple REST API.
CloudFace Vision™ provides a REST API for face recognition. Submit photo URLs, we detect and embed all faces. Then submit a selfie URL to find all matching photos instantly.
Your photos stay in your own storage — we download temporarily, extract face embeddings, then discard the image. Only mathematical vectors are stored on our side.
https://vision.cloudface-ai.com
Every request requires 3 headers. The HMAC signature ensures requests cannot be tampered with or replayed.
| Header | Description |
|---|---|
X-CloudFace-Key | Your API key (starts with cf_live_) |
X-CloudFace-Signature | HMAC-SHA256 of timestamp + request_body using your secret |
X-CloudFace-Timestamp | Current Unix timestamp in seconds |
# Python
import hmac, hashlib, time, json
timestamp = str(int(time.time()))
body_bytes = json.dumps(body).encode() if body else b""
signature = hmac.new(
API_SECRET.encode(),
timestamp.encode() + body_bytes,
hashlib.sha256
).hexdigest()
// Node.js
const crypto = require("crypto");
const timestamp = String(Math.floor(Date.now() / 1000));
const bodyStr = body ? JSON.stringify(body) : "";
const signature = crypto
.createHmac("sha256", API_SECRET)
.update(timestamp + bodyStr)
.digest("hex");
| HTTP Code | Error | Description |
|---|---|---|
| 401 | Invalid API key | Key not found or deactivated |
| 401 | Invalid signature | HMAC mismatch — check secret and body encoding |
| 401 | Request expired | Timestamp older than 5 minutes |
| 401 | Monthly limit exceeded | Upgrade your plan |
| 400 | photos array required | Missing photos field |
| 400 | max 500 photos per request | Split into batches of 500 |
| 404 | event not found | Invalid event_id or wrong API key |
| 500 | Internal error | Contact api@cloudface-ai.com |
| Plan | Monthly Calls | Max Photos/Request | Price |
|---|---|---|---|
| Free | 500 | 500 | ₹0 (1 month trial) |
| Starter | 10,000 | 500 | ₹999/month |
| Growth | 25,000 | 500 | ₹1,999/month |
| Pro | 50,000 | 500 | ₹3,999/month |
| Enterprise | Custom | Custom | Contact us |
Creates a named face index namespace. Returns an event_id used in all subsequent calls.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Event name for your reference. Default: "Untitled" |
# Request
POST /v1/events
{
"name": "Wedding 2026 — John & Sarah"
}
# Response
{
"success": true,
"event_id": "a3f9b2c1-d4e5"
}
Submit photo URLs for face detection and embedding. Photos must be publicly accessible URLs. Processing runs in the background — poll /status to check completion.
| Field | Type | Required | Description |
|---|---|---|---|
| photos | array | required | Array of publicly accessible photo URLs. Max 500 per request. |
# Request
POST /v1/events/a3f9b2c1-d4e5/index
{
"photos": [
"https://your-storage.com/event/photo001.jpg",
"https://your-storage.com/event/photo002.jpg"
]
}
# Response (immediate — processing continues in background)
{
"success": true,
"event_id": "a3f9b2c1-d4e5",
"queued": 2,
"message": "Indexing started."
}
Check indexing progress. Poll this after /index to know when processing is complete.
# Response
{
"success": true,
"event_id": "a3f9b2c1-d4e5",
"name": "Wedding 2026 — John & Sarah",
"status": "ready",
"photo_count": 2,
"face_count": 7,
"last_indexed": "2026-08-12T10:30:00"
}
# status values: "ready" | "indexing" | "error"
Submit a selfie URL. Returns all matching photos from the event index with similarity scores.
| Field | Type | Required | Description |
|---|---|---|---|
| selfie_url | string | required | Publicly accessible URL of the selfie image |
| threshold | float | optional | Match sensitivity 0.5–0.9. Default: 0.7. Lower = more results, higher = stricter |
# Request
POST /v1/events/a3f9b2c1-d4e5/search
{
"selfie_url": "https://your-storage.com/guest_selfie.jpg",
"threshold": 0.7
}
# Response
{
"success": true,
"faces_detected": 1,
"total_matches": 12,
"matches": [
{
"photo_index": "2",
"similarity": 0.94,
"confidence": "94.00%",
"bbox": [120, 80, 340, 380]
}
]
}
import hmac, hashlib, time, json, requests
API_KEY = "cf_live_your_key"
API_SECRET = "your_secret"
BASE_URL = "https://vision.cloudface-ai.com"
def cf_request(method, path, body=None):
timestamp = str(int(time.time()))
body_bytes = json.dumps(body).encode() if body else b""
signature = hmac.new(
API_SECRET.encode(),
timestamp.encode() + body_bytes,
hashlib.sha256
).hexdigest()
headers = {
"X-CloudFace-Key": API_KEY,
"X-CloudFace-Signature": signature,
"X-CloudFace-Timestamp": timestamp,
"Content-Type": "application/json"
}
return requests.request(method, BASE_URL + path, headers=headers, json=body)
const crypto = require("crypto");
const axios = require("axios");
const API_KEY = "cf_live_your_key";
const API_SECRET = "your_secret";
const BASE_URL = "https://vision.cloudface-ai.com";
function cfRequest(method, path, body = null) {
const timestamp = String(Math.floor(Date.now() / 1000));
const bodyStr = body ? JSON.stringify(body) : "";
const signature = crypto
.createHmac("sha256", API_SECRET)
.update(timestamp + bodyStr)
.digest("hex");
return axios({
method, url: BASE_URL + path, data: body,
headers: {
"X-CloudFace-Key": API_KEY,
"X-CloudFace-Signature": signature,
"X-CloudFace-Timestamp": timestamp,
"Content-Type": "application/json"
}
});
}
# Generate signature (bash)
TIMESTAMP=$(date +%s)
BODY='{"name":"My Event"}'
SIGNATURE=$(echo -n "${TIMESTAMP}${BODY}" | openssl dgst -sha256 -hmac "your_secret" | awk '{print $2}')
curl -X POST https://vision.cloudface-ai.com/v1/events \
-H "X-CloudFace-Key: cf_live_your_key" \
-H "X-CloudFace-Signature: $SIGNATURE" \
-H "X-CloudFace-Timestamp: $TIMESTAMP" \
-H "Content-Type: application/json" \
-d "$BODY"
import time
# 1. Create event
resp = cf_request("POST", "/v1/events", {"name": "My Wedding 2026"})
event_id = resp.json()["event_id"]
print(f"Event: {event_id}")
# 2. Index photos in batches of 500
photos = ["https://your-s3.com/photo1.jpg", ...] # your photo URLs
for i in range(0, len(photos), 500):
batch = photos[i:i+500]
cf_request("POST", f"/v1/events/{event_id}/index", {"photos": batch})
# Wait for batch to complete
while True:
s = cf_request("GET", f"/v1/events/{event_id}/status").json()
if s["status"] == "ready": break
time.sleep(3)
print(f"Batch {i//500+1} done: {s['face_count']} faces indexed")
# 3. Search by selfie
result = cf_request("POST", f"/v1/events/{event_id}/search", {
"selfie_url": "https://your-s3.com/guest_selfie.jpg",
"threshold": 0.7
})
data = result.json()
print(f"Found {data['total_matches']} matching photos")
for match in data["matches"]:
print(f" Photo index {match['photo_index']} — {match['confidence']}")
Need help?
Email us at api@cloudface-ai.com — we usually reply within one business day.