Person Integration API¶
This API lets your system create and retrieve Person profiles, change verification status, and manage aliases and photos. All operations run on your system's backend.
Before integrating, read about Person and its use in Workflow and the photo and verification rules.
Setup and authorization¶
Base URL:
Every operation requires an organization api_key with an eligible Person subscription. Pass it in the JSON body or a multipart form field, depending on the method. The key for Workflow session creation belongs to a different API contract.
Do not pass the organization key to a browser or mobile app. Replace <ORGANIZATION_API_KEY>, <PERSON_ID>, <PHOTO_ID>, and <ALIAS_ID> in the examples with your values. Path identifiers are UUIDs.
The response examples include every field in the corresponding schema without omissions. UUIDs, dates, the phone number, and image URLs are fictional; media.example.com illustrates a file URL, not the service's storage address. The examples show different profile states and do not require every operation to be performed in sequence.
All listed operations use POST, including retrieval and deletion. Keep the trailing / in URLs.
| Operation | Path after /api/persons |
Body | Success |
|---|---|---|---|
| Create a person | /create/ |
multipart | 201 |
| List persons | /list/ |
JSON | 200 |
| Retrieve by UUID | /{person_id}/ |
JSON | 200 |
| Retrieve by alias | /retrieve/ |
JSON | 200 |
| Change status | /{person_id}/update/ |
JSON | 200 |
| Add an alias | /{person_id}/alias/ |
JSON | 201 |
| Delete an alias | /{person_id}/alias/{alias_id}/delete/ |
JSON | 204 |
| Add a photo | /{person_id}/photo/ |
multipart | 201 |
| Update photo properties | /{person_id}/photo/{photo_id}/update/ |
JSON | 200 |
| Delete a photo | /{person_id}/photo/{photo_id}/delete/ |
JSON | 204 |
This controller has no operations for deleting a Person, editing an alias, or replacing a photo file. To replace an alias, add and delete aliases; for a new image, upload a separate photo.
Creating a person¶
POST /api/persons/create/, multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
api_key |
string | Yes | Organization key |
is_verified |
boolean | Yes | Initial verification status |
photo_type |
string | Yes | DIGITAL, SCAN, LIVE, or OTHER |
image |
file | Yes | A file with the .jpg, .jpeg, or .png extension |
aliases |
Repeated field containing a JSON object | No | Each object contains value and type; defaults to an empty list |
value is a string of up to 255 characters. Allowed user-supplied alias types are CUSTOM, PHONE, PERSONAL_NUMBER, and DOCUMENT_NUMBER. SYSTEM_ID is generated automatically and equals the person's UUID.
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/create/' \
--form-string 'api_key=<ORGANIZATION_API_KEY>' \
--form-string 'is_verified=false' \
--form-string 'photo_type=OTHER' \
--form 'image=@/path/to/photo.jpg' \
--form-string 'aliases={"value":"customer-1042","type":"CUSTOM"}' \
--form-string 'aliases={"value":"+77000000000","type":"PHONE"}'
Pass each alias as a separate aliases field containing a JSON object, not as a single JSON array. Do not set the multipart Content-Type manually: cURL adds the boundary.
The initial photo becomes the permanent default with source MANUAL. Person creation has no expires_at parameter: add a temporary photo to an existing person in a separate request.
201 Created response:
{
"id": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"is_verified": false,
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:00:00.000",
"aliases": [
{
"id": "43183343-b019-4f90-9037-3cc795361582",
"value": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"type": "SYSTEM_ID",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "SYSTEM"
},
{
"id": "91b0d786-a980-4ed2-95ef-94a9f3f228f1",
"value": "customer-1042",
"type": "CUSTOM",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
},
{
"id": "de48cfd8-2e62-4807-a6a1-e7d6407ee2c9",
"value": "+77000000000",
"type": "PHONE",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"photos": [
{
"id": "08694897-00d0-47e7-b950-b03e03f1ddf2",
"type": "OTHER",
"content": "https://media.example.com/persons/reference.jpg",
"is_uploaded": true,
"is_default": true,
"expires_at": null,
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
]
}
Nested object structures are described below. Save id for subsequent operations. An alias conflict rolls back creation; no partial profile is created.
Retrieving a person¶
By UUID¶
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>"}'
200 OK response for a profile after a successful session:
{
"id": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"is_verified": true,
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:15:00.000",
"aliases": [
{
"id": "43183343-b019-4f90-9037-3cc795361582",
"value": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"type": "SYSTEM_ID",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "SYSTEM"
},
{
"id": "91b0d786-a980-4ed2-95ef-94a9f3f228f1",
"value": "customer-1042",
"type": "CUSTOM",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
},
{
"id": "de48cfd8-2e62-4807-a6a1-e7d6407ee2c9",
"value": "+77000000000",
"type": "PHONE",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"photos": [
{
"id": "08694897-00d0-47e7-b950-b03e03f1ddf2",
"type": "OTHER",
"content": "https://media.example.com/persons/reference.jpg",
"is_uploaded": true,
"is_default": true,
"expires_at": null,
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"flow_sessions": [
{
"id": "fa688ecc-8a47-4d33-aabf-ad4755ca5b99",
"created_at": "2026-09-15T10:05:00.000",
"finished_at": "2026-09-15T10:15:00.000",
"flow": {
"id": "1a0ca936-53e0-41e4-b99e-e9f80574a70b",
"name": "returning-customer",
"display_name": "Repeat verification",
"created_at": "2026-09-01T09:00:00.000",
"updated_at": "2026-09-01T09:00:00.000",
"technologies": [
"PS",
"LC",
"PPS",
"F2F"
]
}
}
],
"actions": [
{
"type": "VERIFY_PERSON",
"created_by": "FLOW",
"created_at": "2026-09-15T10:15:00.000"
},
{
"type": "ADD_ALIAS",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "ADD_ALIAS",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "ADD_PHOTO",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "CREATE_PERSON",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
}
]
}
By exact alias value¶
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/retrieve/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>","alias":"customer-1042"}'
alias is a required string. Lookup uses an active alias value within the organization. Do not pass the type.
The 200 OK response contains the same complete profile as retrieval by UUID:
{
"id": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"is_verified": true,
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:15:00.000",
"aliases": [
{
"id": "43183343-b019-4f90-9037-3cc795361582",
"value": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"type": "SYSTEM_ID",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "SYSTEM"
},
{
"id": "91b0d786-a980-4ed2-95ef-94a9f3f228f1",
"value": "customer-1042",
"type": "CUSTOM",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
},
{
"id": "de48cfd8-2e62-4807-a6a1-e7d6407ee2c9",
"value": "+77000000000",
"type": "PHONE",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"photos": [
{
"id": "08694897-00d0-47e7-b950-b03e03f1ddf2",
"type": "OTHER",
"content": "https://media.example.com/persons/reference.jpg",
"is_uploaded": true,
"is_default": true,
"expires_at": null,
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"flow_sessions": [
{
"id": "fa688ecc-8a47-4d33-aabf-ad4755ca5b99",
"created_at": "2026-09-15T10:05:00.000",
"finished_at": "2026-09-15T10:15:00.000",
"flow": {
"id": "1a0ca936-53e0-41e4-b99e-e9f80574a70b",
"name": "returning-customer",
"display_name": "Repeat verification",
"created_at": "2026-09-01T09:00:00.000",
"updated_at": "2026-09-01T09:00:00.000",
"technologies": [
"PS",
"LC",
"PPS",
"F2F"
]
}
}
],
"actions": [
{
"type": "VERIFY_PERSON",
"created_by": "FLOW",
"created_at": "2026-09-15T10:15:00.000"
},
{
"type": "ADD_ALIAS",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "ADD_ALIAS",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "ADD_PHOTO",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
},
{
"type": "CREATE_PERSON",
"created_by": "API",
"created_at": "2026-09-15T10:00:00.000"
}
]
}
To read historical data, append ?include_expired=true to either method's URL. The default is false: expired aliases and photos are hidden. Deleted photos are excluded in both cases.
include_expired=true does not allow exact lookup by an expired alias. Use the UUID or another active alias.
List and filters¶
POST /api/persons/list/ accepts only api_key in JSON; filters and pagination are passed in the query string.
| Query parameter | Type | Purpose |
|---|---|---|
limit |
integer | Page size |
offset |
integer | Offset from the beginning of the list |
is_verified |
boolean | Filter by current status, including the effects of temporary photo expiration |
alias |
string | Case-insensitive substring search |
flow_session_id |
string | Filter by associated session |
from_date |
datetime | Person creation date on or after this value |
to_date |
datetime | Person creation date on or before this value |
include_expired |
boolean | Include expired data within profiles; defaults to false |
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/list/?limit=20&offset=0&is_verified=true' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>"}'
200 OK response with one person:
{
"count": 1,
"items": [
{
"id": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"is_verified": true,
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:15:00.000",
"aliases": [
{
"id": "43183343-b019-4f90-9037-3cc795361582",
"value": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"type": "SYSTEM_ID",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "SYSTEM"
},
{
"id": "91b0d786-a980-4ed2-95ef-94a9f3f228f1",
"value": "customer-1042",
"type": "CUSTOM",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
},
{
"id": "de48cfd8-2e62-4807-a6a1-e7d6407ee2c9",
"value": "+77000000000",
"type": "PHONE",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
],
"photo": "https://media.example.com/persons/reference.jpg"
}
]
}
For an empty result set:
count is the number of records before pagination; items is the current page. photo is a photo URL or null. Newest profiles appear first by default.
The list's alias filter differs from exact lookup: it can find a profile by an expired alias even if that alias is hidden in the response. Multiple matching aliases for the same person can produce duplicate entries. To retrieve a profile unambiguously, use /retrieve/ or its UUID.
Changing verification status¶
POST /api/persons/{person_id}/update/.
Required JSON fields: api_key (string) and is_verified (boolean).
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/update/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>","is_verified":false}'
200 OK response:
{
"id": "c1572b7e-86cc-4cd4-92bb-c222f18dad1d",
"is_verified": false,
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:20:00.000"
}
Setting true is an explicit decision by the organization, not a request to run face verification. The returned status accounts for temporary photo expiration.
Aliases¶
Add¶
POST /api/persons/{person_id}/alias/.
Required JSON fields: api_key, value (string, up to 255 characters), and type (one of the four user-supplied types listed in the creation section).
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/alias/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>","value":"customer-1042","type":"CUSTOM"}'
201 Created response for a profile that does not yet have this alias:
{
"id": "91b0d786-a980-4ed2-95ef-94a9f3f228f1",
"value": "customer-1042",
"type": "CUSTOM",
"is_expired": false,
"expired_at": null,
"expiration_reason": null,
"source_technology_code": "MANUAL"
}
The value must be unique within the organization, including stored expired aliases. Object fields are described below.
Delete¶
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/alias/<ALIAS_ID>/delete/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>"}'
Response:
The body is empty: no JSON is returned. SYSTEM_ID cannot be deleted. Deleting an alias removes the record itself; it does not move it into history through is_expired.
Adding a photo¶
POST /api/persons/{person_id}/photo/, multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
api_key |
string | Yes | Organization key |
image |
file | Yes | .jpg, .jpeg, or .png |
photo_type |
string | Yes | DIGITAL, SCAN, LIVE, OTHER |
is_default |
boolean | Yes | Set as default; a temporary photo becomes the default regardless of this value |
expires_at |
datetime with timezone | No | Future expiry date; if omitted, the photo is permanent |
Temporary photo example:
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/photo/' \
--form-string 'api_key=<ORGANIZATION_API_KEY>' \
--form-string 'photo_type=OTHER' \
--form-string 'is_default=true' \
--form-string 'expires_at=2030-10-01T12:00:00+05:00' \
--form 'image=@/path/to/current-photo.jpg'
Choose a date that is still in the future. For a permanent photo, omit expires_at.
201 response:
{
"id": "095d4c86-bb7b-4347-a1db-ec62618bc7e2",
"type": "OTHER",
"is_default": true,
"is_uploaded": true,
"expires_at": "2030-10-01T12:00:00+05:00",
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:00:00.000"
}
The upload response contains neither the file URL nor history fields. Retrieve the profile for those fields. See Photos and verification for assignment and restoration rules.
Updating a photo and extending its validity¶
POST /api/persons/{person_id}/photo/{photo_id}/update/, JSON.
| Field | Type | Required | Description |
|---|---|---|---|
api_key |
string | Yes | Organization key |
type |
string or null | No | New type; null is ignored |
is_default |
boolean or null | No | Default assignment; null is ignored |
expires_at |
datetime with timezone | No | New future expiry for an active temporary photo; explicit null is prohibited |
The field is named type for updates and photo_type for uploads. Omitted fields are unchanged. This method does not accept an image file.
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/photo/<PHOTO_ID>/update/' \
--header 'Content-Type: application/json' \
--data '{
"api_key":"<ORGANIZATION_API_KEY>",
"expires_at":"2030-11-01T12:00:00+05:00"
}'
200 OK response after changing the expiry:
{
"id": "095d4c86-bb7b-4347-a1db-ec62618bc7e2",
"type": "OTHER",
"is_default": true,
"is_uploaded": true,
"expires_at": "2030-11-01T12:00:00+05:00",
"created_at": "2026-09-15T10:00:00.000",
"updated_at": "2026-09-15T10:30:00.000"
}
To assign a permanent photo as the default, pass is_default=true. This is allowed if there is no active temporary photo and the selected photo is neither expired nor deleted.
Deleting a photo¶
curl --request POST \
--url 'https://kyc.biometric.vision/api/persons/<PERSON_ID>/photo/<PHOTO_ID>/delete/' \
--header 'Content-Type: application/json' \
--data '{"api_key":"<ORGANIZATION_API_KEY>"}'
Response:
The body is empty: no JSON is returned. A permanent default photo cannot be deleted. A temporary default photo can be deleted; the system then restores a permanent photo.
Response fields¶
Complete profile¶
| Field | Type | Description |
|---|---|---|
id |
UUID | Person identifier |
is_verified |
boolean | Current verification status |
created_at, updated_at |
datetime | Creation and update timestamps |
aliases |
array | Aliases, subject to include_expired |
photos |
array | Photos, subject to expiry and include_expired |
flow_sessions |
array | Associated sessions |
actions |
array | Action history |
flow_sessions and actions are included in detailed retrieval; creation returns the profile without those two arrays. A status update returns only the four scalar fields.
Alias¶
id (UUID), value (string), type (string), is_expired (boolean), expired_at (datetime or null), expiration_reason (string or null), source_technology_code (string).
Photo within a profile¶
id (UUID), type (string), content (URL or null), is_uploaded (boolean), is_default (boolean), expires_at (datetime or null), is_expired (boolean), expired_at (datetime or null), expiration_reason (string or null), source_technology_code (string).
content is a file URL, not Base64. Expiry and activity fields are described in Photo history. Photo upload and update responses differ: they include created_at and updated_at, but not content, is_expired, expired_at, expiration_reason, or source_technology_code.
Session and action¶
A session contains id, created_at, finished_at (which may be null), and flow. The flow object contains id, name, display_name, created_at, updated_at, and technologies, a list of codes. For technology results, use the session result API.
An action contains type, created_by, and created_at. Types: CREATE_PERSON, ADD_PHOTO, ADD_ALIAS, DELETE_PERSON, DELETE_PHOTO, DELETE_ALIAS, VERIFY_PERSON, UNVERIFY_PERSON, UPDATE_PHOTO, UPDATE_ALIAS, EXPIRE_PHOTO, EXPIRE_ALIAS, DEDUPLICATE_PHOTO, DEDUPLICATE_ALIAS. Action sources: SYSTEM, FLOW_METADATA, FLOW, API, or CABINET. History may include actions from other interfaces even if the Integration API has no corresponding operation.
Errors¶
For business rule errors, the response usually contains a detail string. Example:
| HTTP | Situation |
|---|---|
| 400 | Alias conflict, Person limit exceeded, ineligible subscription, unsupported file extension, or violation of photo rules |
| 404 | Invalid organization key; person not found within the organization; photo or alias does not belong to the specified person |
| 422 | Missing required field, invalid UUID or type, prohibited SYSTEM_ID, invalid date format, or a date without a timezone |
Complete 400 Bad Request response for an alias conflict:
Complete 404 Not Found response when the person is not found within the organization:
Complete 422 Unprocessable Entity response when expires_at:null is supplied in a photo update:
{
"detail": [
{
"type": "datetime_type",
"loc": [
"body",
"input_data",
"expires_at"
],
"msg": "Input should be a valid datetime"
}
]
}
For validation errors, detail contains a list of field errors. For alias conflicts, conflicts lists the conflicting values.
Photo detail message (HTTP 400) |
Action |
|---|---|
expires_at must be a future datetime with a timezone |
Supply a future date; a missing timezone is rejected earlier by validation with 422 |
Delete the active temporary photo or wait until it expires |
Delete the current temporary photo or wait for it to expire |
Cannot change default while a temporary photo is active |
Do not switch the default while a temporary photo is active |
Cannot extend an expired or deleted temporary photo |
Upload a new temporary photo |
Cannot convert permanent and temporary photos |
Create a new photo with the required permanence |
Cannot delete default person photo |
Assign another default before deleting a permanent default photo |
Cannot set expired or deleted person photo as default |
Choose an active photo |
In the Integration API, an explicit expires_at:null in an update returns 422. The conversion message applies, for example, when trying to set an expiry on a permanent photo.
Practical scenario¶
- Find a Person by alias, or create a profile if needed.
- Upload a temporary photo and save its UUID.
- Create a session with the same alias and the key of the required Workflow, with Person photo use enabled.
- Retrieve the new verification result.
- If needed, change the expiry before it is reached, or delete the temporary photo.
- Retrieve the profile again and account for its current default photo and
is_verified.
To replace a temporary photo, delete it and then upload the replacement. If the upload fails after deletion, the old temporary reference has already been removed; retrieve the profile and handle that state in your system.