3. Resources
Fields marked with * are mandatory in order to use the APIs correctly.
IMPORTANT:
- All the examples of calls to the APIs below point to the URLs of the SANDBOX environment. For more details on the URLs of the environments, see API Reference.
- There are URLs that are available for the SDK context and also for the Backoffice. Pay attention to this when there is a sdk placeholder in the URL, because it must be replaced according to the use case, and can take on the values “sdk” or “backoffice”.
Recommended Backoffice flow
- For
/backoffice/*routes, usex-api-keydirectly on each request. - The
/backoffice/v1/handshakeendpoint is legacy, kept for backward compatibility, and is being deprecated. - When examples in this page use
Authorization: Bearer <SessionToken>, treat them as legacy Backoffice flow. - In direct backoffice flow, the operational
sessionIdis returned in the response payload (success and error).
Example (direct API key flow):
curl --request POST \
--url https://api-sandbox.fortface.ai/backoffice/v1/identify \
--header 'Content-Type: application/json' \
--header 'x-api-key: string' \
--data '{
"externalUserId": "string",
"imgData": "base64"
}'
3.1 Handshake
Description
The Fortface API has a proprietary session creation system. After the user has gone through the accreditation stage, they can create temporary sessions with restricted access to actions previously determined by the system, built from Handshake.
Before detailing the Handshake header fields and processing steps, it is important to address the process of encrypting and decrypting the device fingerprint.
The handling of data linked to any internal Fortface process follows a strict security process. One of the most used pieces of data during all processes is the device fingerprint, and a specific contract was used to encapsulate it securely in the request.
Now that the encryption and decryption process has been explained, let's go back to talking about the query fields in the Handshake header, which are:
-
Content-Type: Informing the reading nature of theapplication/jsonfield -
x-api-key: Security key configured for the client.
Below is the body needed for the Handshake, and the X-API-KEY field in the header is needed to identify the requesting client and its permissions.
Endpoint: /handshake
Method: POST
Payload:
galleryId*: Identifier of the user's gallery.accountName*: Identifier of the user's account.action*: Action to be performed:enroll | identify | search | liveness | update-enroll | delete-enroll.deviceRequestInfo*: Encrypted information about the device from which the event originated.externalTransactionId: External transaction used to group the sessions. (optional) The strong user identifier is externalUserId (used in enroll, identify, and capture endpoints).
Request (Example)
context: sdk or backoffice
sdk/handshake : Generates a valid session for an action via SDK
backoffice/handshake : Generates a valid session for an action via Backoffice
Example: A session generated sdk/handshake will not be valid for the backoffice/liveness endpoint, but for sdk/liveness.
curl --request POST \
--url https://api-sandbox.fortface.ai/{context}/v1/handshake \
--header 'Content-Type: application/json' \
--header 'x-api-key: string' \
--data '{
"galleryId": "string",
"accountName": "string",
"action": "String<enroll | identify | search | liveness | update-enroll | delete-enroll>",
"deviceRequestInfo": "string",
"externalTransactionId": "string"
}'
Response (Example)
"body": {
"sessionToken": "TOKEN DE SESSÃO PARA ACESSO AOS RECURSOS DA API",
"sessionKey": "CHAVE DA SESSÃO UTILIZADA NO SDK",
"sessionId": "IDENTIFICADOR DA SESSÃO GERADA PELO HANDSHAKE"
}
Processing steps
-
The device fingerprint is encrypted and extracted from “deviceRequestInfoNaN” and then decrypted.
-
In this step, the hash of the device fingerprint is checked. The hash is generated by a function that associates a hash with each deviceInfo field. The Fortface API uses the same system as the SDK to generate the local hash based on the data in the deviceInfo field that the decrypted “deviceRequestInfoNaN” has. This allows a layer to be created to check the reliability and structural integrity of the data in each request to theHandshake approach.
-
A session is created by the existence of a gallery, as informed by the
galleryIdproperty. The api-key associated with this gallery must have permission to perform the Handshake.
| Context | API | HTTP Methods | Version | Handshake Action |
|---|---|---|---|---|
| SDK | handshake | POST | V1 | N/A |
| SDK | enroll | POST | V1 | enroll |
| SDK | identify | POST | V1 | identify |
| SDK | search | POST | V1 | search |
| SDK | liveness | POST | V1 | liveness |
| SDK | capture | POST | V1 | capture |
| Backoffice | handshake | POST | V1 | N/A |
| Backoffice | enroll | POST, PUT, DELETE | V1 | enroll, update-enroll, delete-enroll |
| Backoffice | identify | POST | V1 | identify |
| Backoffice | search | POST | V1 | search |
| Backoffice | liveness | POST | V1 | liveness |
| Backoffice | capture | POST | V1 | capture |
| Backoffice | photo | GET | V1 | N/A |
| Backoffice | log session | GET | V1 | N/A |
3.2 Enroll
The Fortface API has the service of registering the user's face. The request for the resource must have the following valid fields.
Handshake Action: enroll
Endpoint: /enroll
method: POST
Headers
-
Content-Type: Informing the reading nature of the application/json field -
Authorization: Bearer token generated via/handshake(Handshake SessionToken) for SDK and legacy Backoffice flow. -
x-api-key: Recommended header for direct Backoffice calls (without handshake).
Payload:
externalUserId*: User identifier.key*: Key generated by the Fortface SDK.data*: Encrypted user data.(🔓 SDK ).imgData*: Image data (SDK/Encrypted or BackOficce/Base64).returnPhoto: Optional flag indicating the return of the photo in the reponse (🔓 SDK).
Request (Example)
context: sdk or backoffice
curl --request POST \
--url https://api-sandbox.fortface.ai/{context}/v1/enroll \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer (SessionToken of handshake) \
--data '{
“imgData": ‘String <Returned from SDK> or <Base64 in Backofice>’,
“externalUserId": ‘String’,
“key": ‘String <Returns from SDK>’,
“data": ‘String <Returns from SDK>’,
“returnPhoto": ”Boolean”
}'
Response (example)
"photo":{
"liveness":{
"value":false,
"confidence":100
},
"eyesOpen":{
"left":{
"value":true,
"confidence":0
},
"right":{
"value":true,
"confidence":0
}
}
},
"api":{
"version":"string",
"timestamp":"string",
"env":"string"
},
"sdk":{
"appId":"string",
"brand":"string",
"model":"string",
"platform":"string",
"sdkVersion":"string",
"soVersion":"string"
}
**Processing steps
-
In this step, Enroll validates the user's session and brings back the session data to be used by the use cases.
-
We decrypt the payload and process the enrollment of the image in our galleries.
3.3 Identify
Another feature of the Fortface API is to perform 1:1 identification where we receive an identifier and a photo and return whether the photo is really of that identifier.
Handshake Action: identify
Endpoint: /identify
Method: POST
Headers:
Content-Type: Informing the reading nature of theapplication/jsonfieldAuthorization: Bearer token generated through the/handshakeendpoint (Handshake SessionToken)
Payload:
externalUserId*: User identifier.key*: Key generated by the Fortface SDK.data*: Encrypted user data.(🔓 SDK ).imgData*: Image data (SDK/Encrypted or BackOficce/Base64).returnPhoto: Optional flag indicating the return of the photo in the reponse (🔓 SDK).
Request (Example)
context: sdk or backoffice
curl --request POST \
--url 'https://api-sandbox.fortface.ai/{context}/v1/identify' \
--header 'Authorization: Bearer (SessionToken of handshake)' \
--header 'Content-Type: application/json' \
--data '{
“imgData": ‘String <Returned from SDK> or <Base64 in Backofice>’,
“externalUserId": ‘String’,
“key": ‘String <Returns from SDK>’,
“data": ‘String <Returns from SDK>’,
“returnPhoto": ”Boolean”
}'
Response (Example)
{
{
"matchLevel": {
"value": 0
},
"photo": {
"liveness": {},
"eyesOpen": {}
},
"api": {
"version": "string",
"timestamp": "string",
"env": "string"
},
"sdk": {
"appId": "string",
"brand": "string",
"model": "string",
"platform": "string",
"sdkVersion": "string",
"soVersion": "string"
}
}
}
3.4 Search
Another feature of the Fortface API is to perform the 1:N identification where we receive a photo and return possible matches that this photo has within the informed gallery.
Handshake Action: search
Endpoint: /search
Method: POST
Headers:
Content-Type: Informing the reading nature of theapplication/jsonfieldAuthorization: Bearer token generated via the/handshakeendpoint (Handshake SessionToken)
Payload:
key*: Key generated by the Fortface SDK.data*: Encrypted user data.(🔓 SDK ).imgData*: Image data (SDK/Encrypted or BackOficce/Base64).returnPhoto: Optional flag indicating the return of the photo in the reponse (🔓 SDK).
Request (Example)
context: sdk or backoffice
curl --request POST \
--url 'https://api-sandbox.fortface.ai/{context}/v1/search' \
--header 'Authorization: Bearer (SessionToken of handshake)' \
--header 'Content-Type: application/json' \
--data '{
“imgData": ‘String <Returns from SDK> or <Base64 in Backofice>’,
“key": ‘String <Returns from SDK>’,
“data": ‘String <Returns from SDK>’,
“returnPhoto": ”Boolean”
}'
Response (Example)
{
"matches": [
{
"encodingId": "string",
"externalUserId": "string",
"matchLevel": 15
},
{
"encodingId": "string",
"externalUserId": "string",
"matchLevel": 15
},
{
"encodingId": "string",
"externalUserId": "string",
"matchLevel": 15
},
{
"encodingId": "string",
"externalUserId": "string",
"matchLevel": 13
},
{
"encodingId": "string",
"externalUserId": "string",
"matchLevel": 0
}
],
"photo": {
"liveness": {
"value": true,
"confidence": 100
},
"eyesOpen": {
"left": {
"value": true,
"confidence": 0.0
},
"right": {
"value": true,
"confidence": 0.0
}
},
"api": {
"version": "string",
"timestamp": "string",
"env": "string"
},
"sdk": {
"appId": "string",
"brand": "string",
"model": "string",
"platform": "string",
"sdkVersion": "string",
"soVersion": "string"
}
}
}
3.5 Update Enroll
Another feature of the Fortface API is to update the encoding where we receive the legacy session id and the user id. This is how the encoding is updated using the information/image related to the session and user id.
Handshake Action: update-enroll
Endpoint: /enroll
Method: PUT
Headers:
Content-Type: Informing the reading nature of theapplication/jsonfieldAuthorization: Bearer token generated via the/handshakeendpoint (Handshake SessionToken)
Payload:
sessionId*: Id of the legacy session that was enrolled.externalUserId*: Id of the user related to the Enrollment made.
Request (Example)
curl --request PUT \
--url 'https://api-sandbox.fortface.ai/backoffice/v1/enroll' \
--header 'Authorization: Bearer (SessionToken from handshake)' \
--header 'Content-Type: application/json' \
--data '{
“sessionId": ‘Session identifier’,
“externalUserId": ‘User identifier’,
}'
Response (Example)
{
{
"api": {
"version": "string",
"timestamp": "string",
"env": "string"
}
}
}
**Processing steps
-
This step validates the ID of the legacy session, whether it was executed successfully (isSuccess), and whether the user ID is the same as the one sent in the payload.
-
After the previous processing, it searches the image for the session ID, extracts the image's encoding and updates it.
-
After updating the encoding, a session log is created, which stores the processing information.
3.6 Delete Enroll
Another feature of the Fortface API is to delete the encoding where we receive the user's id. Through the session generated by the handshake, we obtain the rest of the information. This is how the user's encoding is removed.
Handshake Action: delete-enroll
Endpoint: /enroll
Method: DELETE
Headers:
Content-Type: Informing the reading nature of theapplication/jsonfieldAuthorization: Bearer token generated via the/handshakeendpoint (Handshake SessionToken)
Payload:
externalUserId*: Id of the user related to the Enroll made.
Request (Example)
curl --request DELETE \
--url 'https://api-sandbox.fortface.ai/backoffice/v1/enroll' \
--header 'Authorization: Bearer (SessionToken from handshake)' \
--header 'Content-Type: application/json' \
--data '{
“externalUserId": ‘User identifier’,
}'
Response (Example)
{
{
"api": {
"version": "string",
"timestamp": "string",
"env": "string"
}
}
}
3.7 Liveness
Another feature of the Fortface API is to perform liveness (or proof of life), where we receive a photo and perform a thorough analysis to ensure that the person actually sending a photo is not wearing a mask, among other possible forms of fraud for proof of life.
Handshake Action: liveness
Endpoint: /liveness
Method: POST
Headers:
Content-Type: Informing the read-only nature of theapplication/jsonfieldAuthorization: Bearer token generated through the/handshakeendpoint (Handshake SessionToken)
Payload:
key*: Key generated by the Fortface SDK.data*: Encrypted user data.(🔓 SDK ).imgData*: Image data (SDK/Encrypted or BackOficce/Base64).externalUserId: User identifier.externalTransactionId: External transaction used to group sessions.returnPhoto: Optional flag indicating the return of the photo in the reponse (🔓 SDK).
Request (Example)
context: sdk or backoffice
curl --request POST \
--url 'https://api-sandbox.fortface.ai/{context}/v1/liveness' \
--header 'Authorization: Bearer (SessionToken of handshake)' \
--header 'Content-Type: application/json' \
--data '{
“imgData": ‘String <Returns from SDK> or <Base64 in Backofice>’,
“key": ‘String <Returns from SDK>’,
“data": ‘String <Returns from SDK>’,
“externalUserId": ‘String’,
“externalTransactionId": ‘String’,
“returnPhoto": ”Boolean”
}'
Response (Example)
{
"photo": {
"liveness": {
"value": true,
"confidence": 0
}
},
"api": {
"env": "string",
"timestamp": 0,
"version": "string"
}
}
3.8 Face Occlusion
Fortface allows evaluating face occlusion caused by hands, arms, objects, or sunglasses in the following services:
/liveness/enroll/identify/capture
Payload
- No changes are required in the request structure.
- The feature is enabled directly in the client’s gallery.
- Occlusion analysis is independent from
LivenessandMatchLevelanalyses. - Processing time may be slightly longer due to the added complexity.
- The
faceOcclusionfield will be added to the response, containing the analysis results.
Response (Example - No Occlusion)
(...)
"faceOcclusion":
{
"status": "done",
"occlusion": false,
"reason": null,
"additionalReason": null
}
Response (Examples - With occlusion)
- Occlusion – Sunglasses:
"faceOcclusion":
{
"status": "done",
"occlusion": true,
"reason": "SUNGLASSES"
}
- Occlusion – Hands/Arms:
"faceOcclusion":
{
"status": "done",
"occlusion": true,
"reason": "HANDS_ARMS"
}
- Occlusion – Objects:
"faceOcclusion":
{
"status": "done",
"occlusion": true,
"reason": "OBJECT",
"additionalReason": "hat"
}
- Occlusion – Eye Region:
"faceOcclusion":
{
"status": "done",
"occlusion": true,
"reason": "EYE_REGION"
}
Additional Information
- Only one type of occlusion is returned per analysis, even if multiple obstructions are present. For this reason, it is essential to use the field
occlusion = trueas part of the decision logic. The returned occlusion will be the one considered most significant by the model. - Objects are detected but not classified. The system will only indicate that there is an occlusion caused by an object, without specifying whether it is, for example, a cup, a phone, or another item.
- If there are zero or multiple faces, the analysis will not be performed. In these cases, the system will return an error to the client indicating that the verification cannot be carried out.
- The presence of occlusion does not prevent
LivenessandMatchLevelanalyses, but it can reduce accuracy. Faces with significant occlusion have a higher chance of generating false negatives, especially in liveness and face match validations. - Prescription glasses are not classified as occlusion unless they cover critical regions such as eyes or nose. Therefore, users wearing prescription glasses will not have a negative impact on the occlusion analysis.
- When
reason = OBJECT,additionalReasoncan be:hat,headcover,helmet,object,reflex,synthetic,toobright(may include more values in the future).
3.9 Get Image
fortface offers an API to retrieve a photo used in an action (enroll, identify, etc.) via the sessionId. **There is no need to perform a handshake for this endpoint.
Endpoint: /backoffice/v1/sessions/photo/{sessionId}
Path Param: :sessionId - Session identifier
Method: GET
Headers:
Content-Type: Informing the reading nature of theapplication/jsonfieldx-api-key: Security key configured for the client customer.
Request (Example)
curl --request GET \
--url 'https://api-sandbox.fortface.ai/backoffice/v1/sessions/photo/{sessionId}' \
--header 'Content-Type: application/json' \
--header 'x-api-key: string'
Response (Example)
{
"photoUrl": "string",
"content": "string<Base64>"
}
3.10 Storing Transaction Photos
Photo storage by Fortface
Fortface offers the option of storing the photos captured during facial biometrics, strictly following best practices in data protection, encryption and security. The choice of which approach to follow must be informed during the deployment process for internal configuration. If the client chooses this approach, it is important to be aware of the following points:
Rescue of images by SessionID
Photos stored by Fortface can be retrieved using the /sessions/photo/web-doc-1781016489282 endpoint. The retrieval is done using the sessionId generated during the initial authentication process (handshake). It is highly recommended that the client stores the sessionId of each transaction locally to facilitate future access to the images.
curl --location 'https://api-sandbox.fortface.ai/backoffice/v1/sessions/photo/{sessionId}' \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json'
Replace {sessionId} with the session ID and 'your-api-key' with your API key.
Removing images
If the customer wishes to remove one or more photos from the database, or request the complete deletion of the images, this can be done by contacting Fortface support at suporte@fortface.com.br.
Customer Photo Storage
Fortface offers the option of discarding all photos after facial biometrics, storing only a hash of the image for future audits. If the customer chooses this approach, we recommend implementing the following controls:
Use the ReturnPhoto = True feature.
In the SDK endpoints (Enroll, Liveness, Identify and Search), the client can request the return of the photo captured in the request. By setting the ReturnPhoto = True parameter, the image will be returned in Base64 format in the body of the response. To guarantee the integrity of the image, we recommend signing the response payload and storing the image without any type of compression.
Hash Returned in Payload
At the SDK endpoints, the response will include a photo hash generated from the image's Base64 using the SHA-256 algorithm. This hash makes it possible to verify that the photo corresponds exactly to the one generated in the request. Although the hash is provided in the payload, the client does not need to store it locally.
[...]
“hash": ‘dqWBmESjR4+Cu6W5Oo64wMsn0J5hi9hfuQmOTFS3hSmpvkoIn6IZpGv6rBt4M7fMmFMU5uc/kGWwtiSuTOrz1g==’,
“api": {
“env": ‘dev’,
“timestamp": 1726755603473,
“version": ”v1 - 0.15.1”
}
}
Photo validation by sessionId
The client can use the validation endpoint to confirm that a specific photo belongs to the session (sessionId) entered. The request must include the sessionId and the image data in Base64 format.
curl --location 'https://api-sandbox.fortface.ai/backoffice/v1/sessions/photo/validate' \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
“sessionId": ‘08996501-5e34-485c-a1ea-56f3f68a9c42’,
“imageData": ”IMAGE BASE64”
}'
The response will be a boolean, indicating whether or not the photo belongs to that session.
3.11 Hubface - Face and Document Validation in Identity Providers
Hubface allows validating a person's identity using a selfie and their document (CPF). For this validation, the /capture endpoint is used.
Configuration
Hubface can be configured to guarantee approximately 92% to 95% coverage in face and document validation. The configuration must be discussed with Fortface's commercial team prior to use.
- Handshake action**:
capture - Endpoint:
/capture - Method:
POST
Headers
Content-Type:application/json(specifies the type of content in the field)Authorization: Bearer token generated via the/handshakeendpoint (Handshake SessionToken)
Payload
externalUserId: Identifier of the user on the client's systemdocument: CPF of the user the client wishes to validateimgData: Image data (encrypted by SDK or Base64 in BackOffice)key: Key generated by the Fortface SDK (🔓 SDK)data: Encrypted user data (🔓 SDK)returnPhoto: Optional flag to return the photo in the response (🔓 SDK)
Request example
Context: SDK or BackOffice
curl --request POST \
--url 'https://api-sandbox.fortface.ai/{context}/v1/capture' \
--header 'Authorization: Bearer (SessionToken of handshake)' \
--header 'Content-Type: application/json' \
--data '{
“imgData": ‘String <Returns from SDK> or <Base64 in BackOffice>’,
“externalUserId": ‘String’,
“document": ‘String <CPF numbers only>’,
“key": ‘String <Returns from SDK>’,
“data": ”String <Returns from SDK>”
}'
Response (Example)
{
"providers": {
"identity": {
"id": "dac98d50-1997-4d78-b270-d487fd795821",
"score": 5
}
},
"photo": {
"liveness": {
"value": true,
"confidence": 100
}
}
}
Important: Liveness return only for SDK
Rank Interpretation
| Return | Details | Recommendation |
|---|---|---|
| Null | Could not be analyzed | -- |
| 0 | No information about face/CPF | Forward to manual review |
| 1 | High Risk | Automatic Rejection |
| 2 | Medium Risk | Automatic Rejection |
| 3 | Neutral Risk | Forward to manual review |
| 4 | Low Risk | Automatic Approval |
| 5 | Very Low Risk | Automatic Approval |
Sandbox Testing
For Sandbox tests, the last digit of the CPF (0 to 9), sent in the document field of the payload, will return predefined scores:
- Document ending in 0 - Score = 0
- Document ending in 5 - Score = 0
- Document ending in 1 - Score = 1
- Document ending in 2 - Score = 2
- Document ending in 3 - Score = 2
- Document ending in 4 - Score = 2
- Document ending in 6 - Score = 3
- Document ending in 7 - Score = 4
- Document ending in 8 - Score = 4
- Document ending in 9 - Score = 5
3.12 Additional Analyses
FortFace provides optional complementary analyses that can be executed during biometric operations.
These analyses enhance security, validate image quality, and prevent the processing of inappropriate or invalid content.
The available analyses are:
- Liveness Calibration
- Face Occlusion
- NSFW Detection
3.12.1 Supported Analyses by Endpoint
| Analysis | Supported Endpoints |
|---|---|
| Liveness Calibration | /liveness, /capture |
| Face Occlusion | /liveness, /capture, /search, /identify, /enroll |
| NSFW Detection | /liveness, /capture, /identify |
3.12.2 How to Enable Additional Analyses
The activation method depends on the integration context:
SDK
Additional analyses must be configured in the handshake, and they will apply to all subsequent SDK calls.
Backoffice
Analyses must be configured directly within each request, such as /liveness, /identify, /search, etc.
3.12.3 Request Structure
"analysis": {
"livenessCalibration": "enhanced",
"nsfw": true
}
Field Description
| Field | Type | Description |
|---|---|---|
livenessCalibration | string | Defines the calibration mode (e.g., enhanced). |
nsfw | boolean | Enables NSFW content detection. |
faceOcclusion (optional) | boolean | Enables face occlusion detection. |
Note: If an analysis is not supported by the endpoint used, it will be ignored during processing.
3.12.4 Analysis Response Blocks
Each activated analysis will include a dedicated response block returned by FortFace.
Below are examples of the possible outputs:
NSFW Detection – Example Response
"nsfw": {
"isSafe": true,
"confidence": 0
}
Fields:
| Field | Type | Description |
|---|---|---|
isSafe | boolean | Indicates whether the image is classified as safe. |
confidence | number | Classifier confidence level (0–100). |
Face Occlusion – Example Response
"faceOcclusion": {
"status": "done",
"occlusion": false,
"reason": null
}
Fields:
| Field | Type | Description | |
|---|---|---|---|
status | string | Status of the analysis (done, error, etc.). | |
occlusion | boolean | Indicates whether any facial occlusion was detected. | |
reason | string | null | Reason for the occlusion when applicable (e.g., mask, glasses). |
additionalReason | string | null | Additional detail when reason = OBJECT (can be: hat, headcover, helmet, object, reflex, synthetic, toobright; may evolve). |
3.12.5 Usage Examples
SDK – Handshake
{
"apiKey": "YOUR_API_KEY",
"analysis": {
"livenessCalibration": "enhanced",
"nsfw": true,
"faceOcclusion": true
}
}
Backoffice – Example in /liveness
{
"image": "base64-image-data",
"analysis": {
"livenessCalibration": "enhanced",
"faceOcclusion": true,
"nsfw": true
}
}
---