People API
Base URL: https://YOUR-SERVER/api. Send your API key in x-api-key where authentication is required. A key also needs the listed permission; your account's access rules still apply.
API guide · All endpoints · OpenAPI JSON
DELETE /people— Delete peopleGET /people— Get all peoplePOST /people— Create a personPUT /people— Update peoplePOST /people/corrections/{id}/undo— Undo a face correctionPOST /people/merge— Merge peopleGET /people/merge-suggestions— Get merge suggestionsDELETE /people/merge-suggestions/verdicts— Undo a merge suggestion verdictPUT /people/merge-suggestions/verdicts— Record a merge suggestion verdictDELETE /people/{id}— Delete personGET /people/{id}— Get a personPUT /people/{id}— Update personGET /people/{id}/corrections— Get correction historyPOST /people/{id}/merge— Merge peoplePUT /people/{id}/reassign— Reassign facesGET /people/{id}/statistics— Get person statisticsGET /people/{id}/thumbnail— Get person thumbnail
Delete people
DELETE /api/people
Bulk delete a list of people at once.
Authentication: API key. Permission: person.delete.
Request body
Required.
Field definitions: BulkIdsDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/BulkIdsDto"
}
}
}Responses
{
"204": {
"description": ""
}
}Get all people
GET /api/people
Retrieve a list of all people.
Authentication: API key. Permission: person.read.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
closestAssetId | query | No | Closest asset ID for similarity search |
closestPersonId | query | No | Closest person ID for similarity search |
page | query | No | Page number for pagination |
size | query | No | Number of items per page |
withHidden | query | No | Include hidden people |
Parameter types, defaults and constraints
[
{
"name": "closestAssetId",
"required": false,
"in": "query",
"description": "Closest asset ID for similarity search",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
},
{
"name": "closestPersonId",
"required": false,
"in": "query",
"description": "Closest person ID for similarity search",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
},
{
"name": "page",
"required": false,
"in": "query",
"description": "Page number for pagination",
"schema": {
"minimum": 1,
"maximum": 9007199254740991,
"default": 1,
"type": "integer"
}
},
{
"name": "size",
"required": false,
"in": "query",
"description": "Number of items per page",
"schema": {
"minimum": 1,
"maximum": 1000,
"default": 500,
"type": "integer"
}
},
{
"name": "withHidden",
"required": false,
"in": "query",
"description": "Include hidden people",
"schema": {
"type": "boolean"
}
}
]Responses
Field definitions: PeopleResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PeopleResponseDto"
}
}
},
"description": ""
}
}Create a person
POST /api/people
Create a new person that can have multiple faces assigned to them.
Authentication: API key. Permission: person.create.
Request body
Required.
Field definitions: PersonCreateDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonCreateDto"
}
}
}Responses
Field definitions: PersonResponseDto
{
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonResponseDto"
}
}
},
"description": ""
}
}Update people
PUT /api/people
Bulk update multiple people at once.
Authentication: API key. Permission: person.update.
Request body
Required.
Field definitions: PeopleUpdateDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PeopleUpdateDto"
}
}
}Responses
Field definitions: BulkIdResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/BulkIdResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
}Undo a face correction
POST /api/people/corrections/{id}/undo
Reverse one manual face decision from the correction history, while the face still stands as the decision left it (same original, same place, same person). Otherwise 409 with a `reason`.
Authentication: API key. Permission: person.update.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Responses
Field definitions: PersonCorrectionDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonCorrectionDto"
}
}
},
"description": ""
}
}Merge people
POST /api/people/merge
Merge an ordered list of people together into a single person. The final name and birth date are always the first defined value, following the order. Also automatically merges people for other users in the cluster group, skipping people that would result in overriding a previously set name or birth date.
Authentication: API key. Permission: person.merge.
Request body
Required.
Field definitions: MergePersonDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/MergePersonDto"
}
}
}Responses
Field definitions: BulkIdResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/BulkIdResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
}Get merge suggestions
GET /api/people/merge-suggestions
Retrieve suggested pairs of people that may be the same person, based on face similarity, for the guided merge review flow.
Authentication: API key. Permission: person.read.
Responses
Field definitions: MergeSuggestionsResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MergeSuggestionsResponseDto"
}
}
},
"description": ""
}
}Undo a merge suggestion verdict
DELETE /api/people/merge-suggestions/verdicts
Remove the recorded verdict for a pair of people, so the pair can be suggested again. The same person id twice undoes "ignore" for that person.
Authentication: API key. Permission: person.update.
Request body
Required.
Field definitions: PersonMergeVerdictDeleteDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonMergeVerdictDeleteDto"
}
}
}Responses
{
"204": {
"description": ""
}
}Record a merge suggestion verdict
PUT /api/people/merge-suggestions/verdicts
Answer a suggested pair of people: "same" merges them now, "different" never suggests the pair again, "later" skips it for 30 days and "ignore" stops suggesting `personId` with anyone. Replaces an earlier verdict for the same pair (a "later" never replaces a "different"); the pair may be given in either order.
Authentication: API key. Permission: person.update.
Request body
Required.
Field definitions: PersonMergeVerdictCreateDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonMergeVerdictCreateDto"
}
}
}Responses
Field definitions: PersonMergeVerdictResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonMergeVerdictResponseDto"
}
}
},
"description": ""
}
}Delete person
DELETE /api/people/{id}
Delete an individual person.
Authentication: API key. Permission: person.delete.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Responses
{
"204": {
"description": ""
}
}Get a person
GET /api/people/{id}
Retrieve a person by id.
Authentication: API key. Permission: person.read.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Responses
Field definitions: PersonResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonResponseDto"
}
}
},
"description": ""
}
}Update person
PUT /api/people/{id}
Update an individual person.
Deprecated. Avoid this operation in new integrations; use the replacement supported by your server release.
Authentication: API key. Permission: person.update.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Request body
Required.
Field definitions: PersonUpdateDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonUpdateDto"
}
}
}Responses
Field definitions: PersonResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonResponseDto"
}
}
},
"description": ""
}
}Get correction history
GET /api/people/{id}/corrections
Retrieve the manual face decisions made about this person (faces moved onto or off them, "not a face of anyone", merges and moved face boxes), most recent first, a page at a time. Only the owner sees them. A photo that can no longer be shown (trashed, Locked, hidden) is left out of the evidence.
Authentication: API key. Permission: person.read.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
page | query | No | Page number |
size | query | No | Number of decisions per page |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
},
{
"name": "page",
"required": false,
"in": "query",
"description": "Page number",
"schema": {
"minimum": 1,
"maximum": 9007199254740991,
"default": 1,
"type": "integer"
}
},
{
"name": "size",
"required": false,
"in": "query",
"description": "Number of decisions per page",
"schema": {
"minimum": 1,
"maximum": 100,
"default": 25,
"type": "integer"
}
}
]Responses
Field definitions: PersonCorrectionsResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonCorrectionsResponseDto"
}
}
},
"description": ""
}
}Merge people
POST /api/people/{id}/merge
Merge a list of people into the person specified in the path parameter.
Deprecated. Avoid this operation in new integrations; use the replacement supported by your server release.
Authentication: API key. Permission: person.merge.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Request body
Required.
Field definitions: MergePersonDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/MergePersonDto"
}
}
}Responses
Field definitions: BulkIdResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/BulkIdResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
}Reassign faces
PUT /api/people/{id}/reassign
Bulk reassign a list of faces to a different person.
Authentication: API key. Permission: person.reassign.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Request body
Required.
Field definitions: AssetFaceUpdateDto
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/AssetFaceUpdateDto"
}
}
}Responses
Field definitions: PersonResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/PersonResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
}Get person statistics
GET /api/people/{id}/statistics
Retrieve statistics about a specific person.
Authentication: API key. Permission: person.statistics.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Responses
Field definitions: PersonStatisticsResponseDto
{
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PersonStatisticsResponseDto"
}
}
},
"description": ""
}
}Get person thumbnail
GET /api/people/{id}/thumbnail
Retrieve the thumbnail file for a person.
Authentication: API key. Permission: person.read.
Parameters
| Name | Where | Required | Description |
|---|---|---|---|
id | path | Yes | string |
Parameter types, defaults and constraints
[
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
"type": "string"
}
}
]Responses
{
"200": {
"content": {
"application/octet-stream": {
"schema": {
"format": "binary",
"type": "string"
}
}
},
"description": ""
}
}© 2026 Frameleaf Inc. All rights reserved.
Frameleaf and the Frameleaf logo are Trademarks of Frameleaf Inc.