API Reference v1

Face Detection & Recognition API Docs

A single RESTful API to detect faces, identify people, and extract attributes from videos, images and GIFs. Submit a task, poll or listen for the callback, get structured JSON back.

Overview

The Facemint API is a JSON-over-HTTPS REST API. Every request that performs detection or recognition is modelled as an asynchronous task — you submit a task, receive a task_id, and either poll GET /task or wait for a signed webhook callback with the final result.

The same endpoint accepts video, image and animated GIF inputs, at resolutions up to 8K and file sizes up to 2 GB. One call can return bounding boxes, per-face attributes (age, gender, emotion, pose, glasses, mask, quality, 106 landmarks) and identity matches against a face library you control.

Base URL

https://api.facemint.io/v1

Conventions

  • All request and response bodies are application/json encoded in UTF-8.
  • Timestamps are ISO-8601 in UTC (e.g. 2026-04-21T09:30:00Z).
  • Time offsets inside media (start_time, end_time, timestamp) are in seconds as floating-point numbers.
  • Bounding boxes are returned as [x, y, width, height] in pixels, relative to the source frame.
  • Every successful response includes a request_id — include it when you contact support.

Quickstart

Three steps to your first detection:

  1. Grab your API key from the Dashboard.
  2. POST a media URL to /create-detection-task.
  3. Poll /task/{id} or receive the callback.
curl -X POST 'https://api.facemint.io/v1/create-detection-task' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "video",
    "media_url": "https://facemint.io/media.mp4",
    "start_time": 0,
    "end_time": 4,
    "sample_rate": 2,
    "min_face_size": 40,
    "attributes": ["age", "gender", "emotion", "pose", "landmarks"],
    "recognize": 1,
    "library_id": "my-people-lib",
    "callback_url": "https://your-site/cb?id=121233"
  }'
import fetch from "node-fetch";

const res = await fetch("https://api.facemint.io/v1/create-detection-task", {
  method: "POST",
  headers: {
    "x-api-key": process.env.FACEMINT_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    type: "video",
    media_url: "https://facemint.io/media.mp4",
    start_time: 0,
    end_time: 4,
    sample_rate: 2,
    min_face_size: 40,
    attributes: ["age", "gender", "emotion", "pose", "landmarks"],
    recognize: 1,
    library_id: "my-people-lib",
    callback_url: "https://your-site/cb?id=121233",
  }),
});

const { task_id } = await res.json();
console.log(task_id);
import os, requests

resp = requests.post(
    "https://api.facemint.io/v1/create-detection-task",
    headers={"x-api-key": os.environ["FACEMINT_KEY"]},
    json={
        "type": "video",
        "media_url": "https://facemint.io/media.mp4",
        "start_time": 0,
        "end_time": 4,
        "sample_rate": 2,
        "min_face_size": 40,
        "attributes": ["age", "gender", "emotion", "pose", "landmarks"],
        "recognize": 1,
        "library_id": "my-people-lib",
        "callback_url": "https://your-site/cb?id=121233",
    },
    timeout=30,
)
print(resp.json()["task_id"])
Tip. If you don't provide a callback_url, poll GET /task/{task_id} every few seconds — typical videos under 60 seconds finish in under a minute.

Authentication

Every request must carry your API key in the x-api-key header. Keys are created and rotated from your Dashboard.

x-api-key: dfed35b0-350c-11f0-9d91-1607289bbab1
Keep your key server-side. Do not embed it in mobile apps or browser JavaScript. Exposed keys can be rotated from the dashboard, and all requests from a rotated key stop immediately.

Media Support

KindFormatsMax sizeMax resolution
Videomp4, mov, mkv, webm, m4v2 GB7680 × 4320 (8K)
Imagejpg, png, webp, bmp, heic50 MB7680 × 4320 (8K)
Animatedgif, apng200 MB4096 × 4096

You can submit a public URL via media_url or upload raw bytes via the signed upload flow on the dashboard. Private storage (S3 / GCS presigned URLs) is supported out of the box.

POSTCreate Detection Task

/v1/create-detection-task

Kicks off a detection (and optional recognition) task against a piece of media. Returns a task_id immediately; the full face payload arrives via webhook or polling.

Request body

FieldTypeRequiredDescription
typestringyesOne of video, image, gif.
media_urlstringyesPublicly reachable URL of the source media. Accepts presigned S3/GCS URLs.
start_timenumbernoVideo only. Seconds from the start to begin scanning. Default 0.
end_timenumbernoVideo only. Seconds from the start to stop scanning. Default: end of file.
sample_rateintegernoVideo/gif only. Frames per second to analyse. 130. Lower is cheaper and faster. Default 2.
min_face_sizeintegernoMinimum detected face side in pixels. Faces smaller than this are ignored. Default 40.
confidence_thresholdnumberno0–1 float. Detections below this confidence are discarded. Default 0.5.
attributesstring[]noAny of age, gender, emotion, pose, glasses, mask, quality, landmarks. Omit or pass [] for bounding boxes only.
recognizeintegerno0 to skip identity matching, 1 to match against library_id. Default 0.
library_idstringconditionalRequired when recognize=1. The face library to search.
top_kintegernoNumber of top matches returned per face. Default 1, max 10.
callback_urlstringnoHTTPS URL to receive the signed completion webhook. See Webhook Callbacks.
metadataobjectnoFree-form key/value object up to 2 KB — echoed back in the result for correlation.

Example request

POST /v1/create-detection-task
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "type": "video",
  "media_url": "https://facemint.io/media.mp4",
  "start_time": 0,
  "end_time": 4,
  "sample_rate": 2,
  "min_face_size": 40,
  "attributes": ["age", "gender", "emotion", "pose", "landmarks"],
  "recognize": 1,
  "library_id": "my-people-lib",
  "callback_url": "https://your-site/cb?id=121233"
}

Example response — 202 Accepted

{
  "request_id": "req_7f2b1a4c8d",
  "task_id": "task_0195e3ab6f4a7c2d",
  "status": "queued",
  "created_at": "2026-04-21T09:30:00Z",
  "estimated_seconds": 14
}

GETGet Task Result

/v1/task/{task_id}

Returns the current state of a task. Poll at 2–5 s intervals while status is queued or running.

Status values

queuedTask is waiting for a worker.
runningAnalysis in progress.
succeededDone. result field is populated.
failedTerminal failure. See error.
cancelledCancelled via /task/{id}/cancel.

Example — succeeded video task

GET /v1/task/task_0195e3ab6f4a7c2d
x-api-key: YOUR_API_KEY
{
  "request_id": "req_2e0df38b91",
  "task_id": "task_0195e3ab6f4a7c2d",
  "status": "succeeded",
  "type": "video",
  "media": {
    "url": "https://facemint.io/media.mp4",
    "duration": 4.0,
    "width": 1920,
    "height": 1080
  },
  "result": {
    "frames": [
      {
        "timestamp": 0.5,
        "faces": [
          {
            "face_id": "f_01",
            "bbox": [420, 180, 260, 260],
            "confidence": 0.982,
            "attributes": {
              "age": 28,
              "gender": "female",
              "emotion": "happy",
              "pose": { "yaw": -4.3, "pitch": 2.1, "roll": 0.7 },
              "glasses": false,
              "mask": false,
              "quality": 0.91,
              "landmarks": [[432,210],[485,212], "...106 points"]
            },
            "identity": {
              "matches": [
                { "person_id": "p_zhang_wei", "name": "Zhang Wei", "score": 0.89 }
              ]
            }
          }
        ]
      }
    ],
    "face_tracks": [
      { "track_id": "t_1", "person_id": "p_zhang_wei", "appears_at": 0.5, "disappears_at": 3.5 }
    ],
    "summary": { "total_faces": 1, "unique_identities": 1 }
  },
  "created_at": "2026-04-21T09:30:00Z",
  "completed_at": "2026-04-21T09:30:17Z"
}

GETList Tasks

/v1/tasks

Paginated listing of your recent tasks. Supports keyset pagination via cursor.

Query paramTypeDefaultDescription
statusstringFilter by status.
typestringvideo / image / gif.
created_afterISO-8601Only tasks created after this timestamp.
limitinteger20Page size, max 100.
cursorstringOpaque cursor from previous response.

POSTCancel Task

/v1/task/{task_id}/cancel

Cancels a queued or running task. Tasks that have already succeeded or failed return 409.

{
  "task_id": "task_0195e3ab6f4a7c2d",
  "status": "cancelled"
}

Face Library

A face library is a private, searchable collection of reference identities. Pass its library_id with recognize=1 on a detection task to get identity matches for every detected face.

POSTCreate library

/v1/library
{
  "library_id": "my-people-lib",
  "name": "Office staff",
  "description": "Employees allowed at HQ entrance"
}

GETList libraries

/v1/libraries

DELETEDelete library

/v1/library/{library_id}
Deleting a library is permanent and removes all faces and embeddings stored in it.

POSTAdd Face to Library

/v1/library/{library_id}/face

Enrolls one reference image under a person_id. You can add multiple images per person — the service builds a robust embedding from all of them.

FieldTypeRequiredDescription
person_idstringyesStable identifier you assign to this person.
namestringnoDisplay name returned with matches.
image_urlstringyesReference photo URL. Must contain exactly one clear face.
metadataobjectnoCustom attributes (department, role, …).
POST /v1/library/my-people-lib/face
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "person_id": "p_zhang_wei",
  "name": "Zhang Wei",
  "image_url": "https://cdn.example.com/zhangwei/profile.jpg",
  "metadata": { "team": "engineering" }
}

POSTCompare Two Faces

/v1/compare

1:1 verification. Returns a similarity score between two faces. Useful for liveness and login flows.

{
  "source_image_url": "https://example.com/a.jpg",
  "target_image_url": "https://example.com/b.jpg"
}
{
  "request_id": "req_cmp_8a1",
  "score": 0.914,
  "is_same_person": true,
  "threshold": 0.70
}

Attribute Reference

Request attributes via the attributes array on a detection task. Each attribute only adds marginal cost; request only what you need.

AttributeReturn shapeNotes
ageintegerEstimated age in years, 0–100.
gender"male" / "female"Returned with an internal confidence > 0.6 or omitted.
emotionone of neutral, happy, sad, angry, surprised, disgusted, fearfulDominant expression.
pose{yaw, pitch, roll} in degreesHead orientation.
glassesbooleanAny eyewear counts as true.
maskbooleanCovers lower half of face.
qualityfloat 0–1Use this to filter low-quality crops before downstream processing.
landmarksarray of 106 [x, y]Dense landmarks for eyes, brows, nose, mouth and jaw.

Webhook Callbacks

When you provide a callback_url, Facemint POSTs the full task result to it as soon as the task reaches a terminal state.

Headers

Content-Typeapplication/json
X-Facemint-Eventtask.succeeded, task.failed or task.cancelled
X-Facemint-SignatureHex HMAC-SHA256 of the raw body, signed with your webhook secret.
X-Facemint-TimestampUnix epoch seconds; reject deliveries more than 5 minutes old.

Payload

{
  "event": "task.succeeded",
  "task_id": "task_0195e3ab6f4a7c2d",
  "status": "succeeded",
  "result": { "...identical to GET /task/{id}..." }
}

Retries

Non-2xx responses are retried with exponential backoff up to 8 times over 24 hours. Deliveries are considered successful on any 2xx response within 10 seconds.

Verify the signature. Compute HMAC_SHA256(webhook_secret, timestamp + "." + raw_body) and compare using a constant-time check.

Rate Limits

Per-key soft limits. Contact support if you need higher throughput.

PlanRequests / minConcurrent tasksMonthly minutes
Free60260
Starter30081 000
Scale1 2003210 000
Enterprisecustomcustomcustom

Every response carries:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1745229600

When you exceed the limit you receive 429 Too Many Requests with a Retry-After header.

Error Codes

Errors follow a uniform envelope:

{
  "error": {
    "code": "invalid_media",
    "message": "Unable to decode media at media_url.",
    "request_id": "req_7f2b1a4c8d"
  }
}
HTTPcodeMeaning
400invalid_requestMalformed JSON or missing required field.
400invalid_mediaSource file could not be decoded or exceeds size limits.
401unauthorizedMissing or invalid API key.
403forbiddenKey does not have access to this resource (e.g. another account's library).
404not_foundTask, library or person does not exist.
409conflictTask is already in a terminal state and cannot be cancelled.
413payload_too_largeMedia exceeds the plan limit.
422no_faces_detectedNo face met the configured thresholds — still billed as a detection.
429rate_limitedToo many requests. Retry after Retry-After.
500internal_errorTransient. Retry with backoff.
503service_unavailablePlanned maintenance or overload.

Changelog

  • 2026-04-10 — 106-point landmark output is now stable and returned by default when landmarks is requested.
  • 2026-02-18face_tracks added to video task results, grouping the same identity across frames.
  • 2025-11-02 — Increased max video size to 2 GB.
  • 2025-09-05POST /v1/compare 1:1 verification endpoint launched.

Ready to ship?

Grab an API key and run your first detection task in minutes.

Get API Access