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”.
  • For /backoffice/* routes, use x-api-key directly on each request.
  • The /backoffice/v1/handshake endpoint 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 sessionId is 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 the application/json field

  • 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

  1. The device fingerprint is encrypted and extracted from “deviceRequestInfoNaN” and then decrypted.

  2. 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.

  3. A session is created by the existence of a gallery, as informed by the galleryId property. The api-key associated with this gallery must have permission to perform the Handshake.

ContextAPIHTTP MethodsVersionHandshake Action
SDKhandshakePOSTV1N/A
SDKenrollPOSTV1enroll
SDKidentifyPOSTV1identify
SDKsearchPOSTV1search
SDKlivenessPOSTV1liveness
SDKcapturePOSTV1capture
BackofficehandshakePOSTV1N/A
BackofficeenrollPOST, PUT, DELETEV1enroll, update-enroll, delete-enroll
BackofficeidentifyPOSTV1identify
BackofficesearchPOSTV1search
BackofficelivenessPOSTV1liveness
BackofficecapturePOSTV1capture
BackofficephotoGETV1N/A
Backofficelog sessionGETV1N/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 the application/json field
  • Authorization: Bearer token generated through the /handshake endpoint (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"
}
}
}

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 the application/json field
  • Authorization: Bearer token generated via the /handshake endpoint (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 the application/json field
  • Authorization: Bearer token generated via the /handshake endpoint (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 the application/json field
  • Authorization: Bearer token generated via the /handshake endpoint (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 the application/json field
  • Authorization: Bearer token generated through the /handshake endpoint (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 Liveness and MatchLevel analyses.
  • Processing time may be slightly longer due to the added complexity.
  • The faceOcclusion field 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

  1. 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 = true as part of the decision logic. The returned occlusion will be the one considered most significant by the model.
  2. 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.
  3. 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.
  4. The presence of occlusion does not prevent Liveness and MatchLevel analyses, but it can reduce accuracy. Faces with significant occlusion have a higher chance of generating false negatives, especially in liveness and face match validations.
  5. 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.
  6. When reason = OBJECT, additionalReason can 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 the application/json field
  • x-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 /handshake endpoint (Handshake SessionToken)

Payload

  • externalUserId: Identifier of the user on the client's system
  • document: CPF of the user the client wishes to validate
  • imgData: 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

ReturnDetailsRecommendation
NullCould not be analyzed--
0No information about face/CPFForward to manual review
1High RiskAutomatic Rejection
2Medium RiskAutomatic Rejection
3Neutral RiskForward to manual review
4Low RiskAutomatic Approval
5Very Low RiskAutomatic 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

AnalysisSupported 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

FieldTypeDescription
livenessCalibrationstringDefines the calibration mode (e.g., enhanced).
nsfwbooleanEnables NSFW content detection.
faceOcclusion (optional)booleanEnables 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:

FieldTypeDescription
isSafebooleanIndicates whether the image is classified as safe.
confidencenumberClassifier confidence level (0–100).

Face Occlusion – Example Response

"faceOcclusion": {
"status": "done",
"occlusion": false,
"reason": null
}

Fields:

FieldTypeDescription
statusstringStatus of the analysis (done, error, etc.).
occlusionbooleanIndicates whether any facial occlusion was detected.
reasonstringnullReason for the occlusion when applicable (e.g., mask, glasses).
additionalReasonstringnullAdditional 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
}
}

---