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.
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.
https://api.facemint.io/v1
application/json encoded in UTF-8.2026-04-21T09:30:00Z).start_time, end_time, timestamp) are in seconds as floating-point numbers.[x, y, width, height] in pixels, relative to the source frame.request_id — include it when you contact support.Three steps to your first detection:
/create-detection-task./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"
}'
callback_url, poll GET /task/{task_id} every few seconds — typical videos under 60 seconds finish in under a minute.
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
| Kind | Formats | Max size | Max resolution |
|---|---|---|---|
| Video | mp4, mov, mkv, webm, m4v | 2 GB | 7680 × 4320 (8K) |
| Image | jpg, png, webp, bmp, heic | 50 MB | 7680 × 4320 (8K) |
| Animated | gif, apng | 200 MB | 4096 × 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.
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.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | One of video, image, gif. |
media_url | string | yes | Publicly reachable URL of the source media. Accepts presigned S3/GCS URLs. |
start_time | number | no | Video only. Seconds from the start to begin scanning. Default 0. |
end_time | number | no | Video only. Seconds from the start to stop scanning. Default: end of file. |
sample_rate | integer | no | Video/gif only. Frames per second to analyse. 1–30. Lower is cheaper and faster. Default 2. |
min_face_size | integer | no | Minimum detected face side in pixels. Faces smaller than this are ignored. Default 40. |
confidence_threshold | number | no | 0–1 float. Detections below this confidence are discarded. Default 0.5. |
attributes | string[] | no | Any of age, gender, emotion, pose, glasses, mask, quality, landmarks. Omit or pass [] for bounding boxes only. |
recognize | integer | no | 0 to skip identity matching, 1 to match against library_id. Default 0. |
library_id | string | conditional | Required when recognize=1. The face library to search. |
top_k | integer | no | Number of top matches returned per face. Default 1, max 10. |
callback_url | string | no | HTTPS URL to receive the signed completion webhook. See Webhook Callbacks. |
metadata | object | no | Free-form key/value object up to 2 KB — echoed back in the result for correlation. |
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"
}
{
"request_id": "req_7f2b1a4c8d",
"task_id": "task_0195e3ab6f4a7c2d",
"status": "queued",
"created_at": "2026-04-21T09:30:00Z",
"estimated_seconds": 14
}
Returns the current state of a task. Poll at 2–5 s intervals while status is queued or running.
queued | Task is waiting for a worker. |
running | Analysis in progress. |
succeeded | Done. result field is populated. |
failed | Terminal failure. See error. |
cancelled | Cancelled via /task/{id}/cancel. |
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"
}
Paginated listing of your recent tasks. Supports keyset pagination via cursor.
| Query param | Type | Default | Description |
|---|---|---|---|
status | string | – | Filter by status. |
type | string | – | video / image / gif. |
created_after | ISO-8601 | – | Only tasks created after this timestamp. |
limit | integer | 20 | Page size, max 100. |
cursor | string | – | Opaque cursor from previous response. |
Cancels a queued or running task. Tasks that have already succeeded or failed return 409.
{
"task_id": "task_0195e3ab6f4a7c2d",
"status": "cancelled"
}
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.
{
"library_id": "my-people-lib",
"name": "Office staff",
"description": "Employees allowed at HQ entrance"
}
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.
| Field | Type | Required | Description |
|---|---|---|---|
person_id | string | yes | Stable identifier you assign to this person. |
name | string | no | Display name returned with matches. |
image_url | string | yes | Reference photo URL. Must contain exactly one clear face. |
metadata | object | no | Custom 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" }
}
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
}
Request attributes via the attributes array on a detection task. Each attribute only adds marginal cost; request only what you need.
| Attribute | Return shape | Notes |
|---|---|---|
age | integer | Estimated age in years, 0–100. |
gender | "male" / "female" | Returned with an internal confidence > 0.6 or omitted. |
emotion | one of neutral, happy, sad, angry, surprised, disgusted, fearful | Dominant expression. |
pose | {yaw, pitch, roll} in degrees | Head orientation. |
glasses | boolean | Any eyewear counts as true. |
mask | boolean | Covers lower half of face. |
quality | float 0–1 | Use this to filter low-quality crops before downstream processing. |
landmarks | array of 106 [x, y] | Dense landmarks for eyes, brows, nose, mouth and jaw. |
When you provide a callback_url, Facemint POSTs the full task result to it as soon as the task reaches a terminal state.
Content-Type | application/json |
X-Facemint-Event | task.succeeded, task.failed or task.cancelled |
X-Facemint-Signature | Hex HMAC-SHA256 of the raw body, signed with your webhook secret. |
X-Facemint-Timestamp | Unix epoch seconds; reject deliveries more than 5 minutes old. |
{
"event": "task.succeeded",
"task_id": "task_0195e3ab6f4a7c2d",
"status": "succeeded",
"result": { "...identical to GET /task/{id}..." }
}
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.
HMAC_SHA256(webhook_secret, timestamp + "." + raw_body) and compare using a constant-time check.Per-key soft limits. Contact support if you need higher throughput.
| Plan | Requests / min | Concurrent tasks | Monthly minutes |
|---|---|---|---|
| Free | 60 | 2 | 60 |
| Starter | 300 | 8 | 1 000 |
| Scale | 1 200 | 32 | 10 000 |
| Enterprise | custom | custom | custom |
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.
Errors follow a uniform envelope:
{
"error": {
"code": "invalid_media",
"message": "Unable to decode media at media_url.",
"request_id": "req_7f2b1a4c8d"
}
}
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed JSON or missing required field. |
| 400 | invalid_media | Source file could not be decoded or exceeds size limits. |
| 401 | unauthorized | Missing or invalid API key. |
| 403 | forbidden | Key does not have access to this resource (e.g. another account's library). |
| 404 | not_found | Task, library or person does not exist. |
| 409 | conflict | Task is already in a terminal state and cannot be cancelled. |
| 413 | payload_too_large | Media exceeds the plan limit. |
| 422 | no_faces_detected | No face met the configured thresholds — still billed as a detection. |
| 429 | rate_limited | Too many requests. Retry after Retry-After. |
| 500 | internal_error | Transient. Retry with backoff. |
| 503 | service_unavailable | Planned maintenance or overload. |
landmarks is requested.face_tracks added to video task results, grouping the same identity across frames.POST /v1/compare 1:1 verification endpoint launched.Grab an API key and run your first detection task in minutes.
© 2026 Facemint, Inc. All rights reserved.