CloudFace Vision™ API

Face recognition API powered by CloudFace Vision Engine™. Detect, index, and search faces across photo collections with a simple REST API.

Introduction

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.

💡 New here? Request API access — free tier includes 500 calls/month with no credit card required.

Base URL

https://vision.cloudface-ai.com

Authentication

Every request requires 3 headers. The HMAC signature ensures requests cannot be tampered with or replayed.

HeaderDescription
X-CloudFace-KeyYour API key (starts with cf_live_)
X-CloudFace-SignatureHMAC-SHA256 of timestamp + request_body using your secret
X-CloudFace-TimestampCurrent Unix timestamp in seconds
⚠️ Requests older than 5 minutes are automatically rejected. Always use the current timestamp.

Signature generation

# 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");

Error Codes

HTTP CodeErrorDescription
401Invalid API keyKey not found or deactivated
401Invalid signatureHMAC mismatch — check secret and body encoding
401Request expiredTimestamp older than 5 minutes
401Monthly limit exceededUpgrade your plan
400photos array requiredMissing photos field
400max 500 photos per requestSplit into batches of 500
404event not foundInvalid event_id or wrong API key
500Internal errorContact api@cloudface-ai.com

Rate Limits

PlanMonthly CallsMax Photos/RequestPrice
Free500500₹0 (1 month trial)
Starter10,000500₹999/month
Growth25,000500₹1,999/month
Pro50,000500₹3,999/month
EnterpriseCustomCustomContact us

API Reference

Create Event

Creates a named face index namespace. Returns an event_id used in all subsequent calls.

POST/v1/events

Request body

FieldTypeRequiredDescription
namestringoptionalEvent name for your reference. Default: "Untitled"
# Request
POST /v1/events
{
  "name": "Wedding 2026 — John & Sarah"
}

# Response
{
  "success": true,
  "event_id": "a3f9b2c1-d4e5"
}

Index Photos

Submit photo URLs for face detection and embedding. Photos must be publicly accessible URLs. Processing runs in the background — poll /status to check completion.

POST/v1/events/{event_id}/index
FieldTypeRequiredDescription
photosarrayrequiredArray 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."
}
💡 For large collections, split into batches of 500 and submit sequentially. Poll /status after each batch before submitting the next.

Check Status

Check indexing progress. Poll this after /index to know when processing is complete.

GET/v1/events/{event_id}/status
# 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.

POST/v1/events/{event_id}/search
FieldTypeRequiredDescription
selfie_urlstringrequiredPublicly accessible URL of the selfie image
thresholdfloatoptionalMatch 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]
    }
  ]
}

Code Examples

Python — Helper function

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)

Node.js — Helper function

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"
    }
  });
}

cURL

# 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"

Complete Python Example

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.