API Endpoints

This guide details the available endpoints in the ThirdFactor AI API Gateway v0.1.0.

Overview

ThirdFactor.ai provides AI-powered identity verification and document understanding services through this secure API gateway.

Base URL

https://<CUSTOM_URL> — issued to your organisation by ThirdFactor.ai.

Authentication

HTTP Bearer Token — issued to your organisation by ThirdFactor.ai.

Authorization: Bearer <YOUR_ACCESS_TOKEN>

Content Types

Content-Type

Used for

application/x-www-form-urlencoded

Most image-as-base64 inputs

application/json

JSON payloads (e.g., face comparison)

multipart/form-data

File uploads (e.g., raw image conversion)

HTTP Status Codes

Code

Meaning

200

Success

401

Authentication error

422

Input validation failed

500

Internal server error

All requests are authenticated and encrypted over HTTPS. API tokens must be kept confidential.

Note regarding Image Inputs: All endpoints that accept image data (detect face, compare face, etc.) require the images to be uploaded in Base64 format. This design ensures consistent handling of image data across various client platforms and network environments, simplifying the JSON payload structure.

Error Model

Sample validation error (HTTP 422):

{
  "detail": [
    {
      "loc": ["body", "field_name"],
      "msg": "Field is required",
      "type": "value_error.missing"
    }
  ]
}

1. Health Check

Verifies that the API service is operational.

  • Method: GET

  • Endpoint: /health

  • Auth: Not required

Headers

Response (200 OK)

{
  "status": "healthy",
  "service": "thirdfactor-ai-gateway"
}

2. Image to Base64

Converts an uploaded image file into a base64 string. Use this if your client application needs to convert files before sending them to the analysis endpoints.

  • Method: POST

  • Endpoint: /image-to-base64/

  • Auth: Required

  • Content-Type: multipart/form-data

Form Data

Key

Type

Required

Description

image

File

Yes

Image file to convert.

Response (200 OK)

{
  "data_url": "data:image/jpeg;base64,/9j/4AAQ...",
  "content_type": "image/jpeg",
  "filename": "uploaded_image.jpg"
}

3. Detect Face

Detects faces and optional attributes (age range, gender, occlusion, etc.).

  • Method: POST

  • Endpoint: /detect-face/

  • Auth: Required

  • Content-Type: application/x-www-form-urlencoded

Body Parameters

Response (200 OK — faces found)

{
  "result": true,
  "total_faces": 1,
  "faces": [
    {
      "confidence": 0.84,
      "age_range": { "min_age": 27, "max_age": 32, "detected_age": 29 },
      "gender": "Male",
      "occluded": false
    }
  ]
}

Response (200 OK — no faces found)

{ "result": false, "total_faces": 0, "faces": [] }

4. Analyze Liveness

Analyzes a video file to verify liveness and detecting potential spoofing attempts.

  • Method: POST

  • Endpoint: /api/analyze-liveness

  • Auth: Not required

  • Content-Type: multipart/form-data

Body Parameters (form-data)

Response (200 OK)

{
  "analysis": {
    "liveness_score": "0.70",
    "antispoof_score": "1.00",
    "blink_count": 0
  },
  "antispoof_score": "1.00",
  "blink_count": 0,
  "liveness_score": "0.70",
  "frames": [
    0: "data:image/jpeg;base64,/9j/4AAQ...",
    1:"data:image/jpeg;base64,/9j/4AAQ..."
  ],
  "is_live": true
}

5. Compare Face (1:1)

Compares two face images to verify if they belong to the same person.

  • Method: POST

  • Endpoint: /compare-face/

  • Auth: Required

  • Content-Type: application/json

Query Parameters

Key

Default

Description

threshold

52.0

Similarity threshold (float) for matching.

live_check

false

Optional liveness check (boolean).

occlusion_check

false

Check for face obstructions (boolean).

Body (JSON Array)

[
  "<BASE64_IMAGE_1>",
  "<BASE64_IMAGE_2>"
]

Response (200 OK — match)

{
  "verified": true,
  "confidence": 98.5,
  "percentage_match": 99.9
}

Response (200 OK — no match)

{
  "verified": false,
  "percentage_match": 0
}

6. Compare Face (1:N)

Performs a reverse search to find a face match within a pre-ingested database.

  • Method: POST

  • Endpoint: /api/face-reverse-search

  • Auth: Not required

  • Content-Type: binary

Body

  • Binary File: Upload the image file as the raw body content.

Response (200 OK)

{
    "matches": [
        {
            "id": 6,
            "score": 0.0,
            "metadata": {
                "filename": "ingest_1764663714_user.jpg"
            }
        },
        {
            "id": 25,
            "score": 0.32,
            "metadata": {
                "filename": "ingest_1768883379_FRONT.jpg"
            }
        }
    ],
    "query_time_seconds": 1.38,
    "search_time_seconds": 0.00007,
    "query_image": "/static/uploads/query_1769539703.jpg",
    "total_time_seconds": 1.39
}

8. Detect & Crop Document

Automatically detects the type of document and returns a cropped image.

  • Method: POST

  • Endpoint: /type-of-document-crop/

  • Auth: Required

  • Content-Type: application/x-www-form-urlencoded

Supported Document Types:

The API recognises the following document types:

  • citizenship-front / citizenship-back

  • driving-license

  • passport-front / passport-back

  • pan-id

  • disability-id

  • national-id

  • voter-id

  • foreign-passport

Body Parameters

Key

Type

Required

Description

base64_image

string

Yes

Base64 encoded string of the document image.

Response (200 OK)

{
  "document_type": "national-id-front",
  "score": 0.98,
  "cropped_image": "data:image/jpeg;base64,/9j/..."
}

9. Analyze Document (OCR)

Performs OCR and structured information extraction from supported document types.

  • Method: POST

  • Endpoint: /document-extract-information/

  • Auth: Required

  • Content-Type: application/x-www-form-urlencoded

Body Parameters

Key

Type

Required

Description

base64_image

string

Yes

Base64 encoded string of the document image.

Response (200 OK)

{
  "success": true,
  "data": {
    "id_number": "XXXX-XXXX-XXXX",
    "name": "Jane Smith",
    "address": "Sample Address",
    "gender": "F",
    "dob": { "year": "1995", "month": "07", "day": "10" },
    "detected_type": "national-id",
    "confidence": 0.97
  }
}

10. Detect Forgery

Analyzes an image to detect potential manipulation or forgery.

  • Method: POST

  • Endpoint: /api/analyze

  • Auth: Not required

  • Content-Type: multipart/form-data

Body Parameters (form-data)

Response (200 OK)

{
    "is_forged": false,
    "original_image": "/static/uploads/original_ID.png",
    "highlighted_image": "/static/uploads/overlay_ID.png",
    "analysis": {
        "status": "AUTHENTIC",
        "forgery_score": "0.13",
        "details": "No manipulation detected"
    }
}

11. Generate KYC URL (SDK)

Generates a dynamic URL for the ThirdFactor SDK authentication process. To use this endpoint, you must first generate a signed JWT token.

1. Generate JWT Token

Create a JWT token signed with HMAC SHA256 (HS256) using your provided Secret.

  • Header:

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • Payload:

    {
      "sub": "1234567890",
      "name": "Jane User",
      "iss": "<YOUR_ISSUER_ID>",
      "token": "<YOUR_TOKEN>",
      "iat": 1516239022,
      "identifier": "9888888888",
      "label": "Jane User",
      "secondary_label": "jane",
      "callback": "https://your-webhook.com/callback-id",
      "is_sdk": true
    }
    
    • callback: The URL where the results of the KYC Verification will be sent via webhook.

2. Make the Request

  • Method: POST

  • Request URL: https://<thirdfactor_URL>/tfauth/get-kyc-url/

  • Content-Type: application/json

Request Body:

Include the generated JWT token in the JSON body.

{
    "jwt_token": "<YOUR_GENERATED_JWT_TOKEN>"
}

Response (200 OK)

{
    "url": "https://endpoint/tfauth/start?",
    "remaining_credits": 97
}

Response (Error - Invalid Token)

{
  "error": "Invalid token or token does not belong to tenant: <Org Name>"
}

Response (Error - Insufficient Credits)

{
  "error": "Insufficient credits. Available credits: 0. 1 credit is required to generate KYC URL."
}

11.1 Webhook Notification (Full Payload)

When the KYC process is completed, the SDK server sends a notification to the callback URL specified in the payload. The payload provides a complete log of the detection and verification process.

Example Payload Structure:

{
  "documentDetectionLog": [
    {
      "created_at": "2026-01-27 10:43:26.644142+00:00",
      "is_verified": true,
      "nationality": "nepali",
      "document_number": "11111111",
      "photo": "<BASE64_STRING_OF_SCANNED_DOC>",
      "original_photo": "<BASE64_STRING_OF_ORIGINAL_FRAME>",
      "claimed_doc_type": "citizenship-back",
      "detected_doc_type": "citizenship-back",
      "reason": "Valid Type"
    },
    {
      "created_at": "2026-01-27 10:43:27.201931+00:00",
      "is_verified": true,
      "nationality": "nepali",
      "document_number": "11111111",
      "photo": "<BASE64_STRING>",
      "original_photo": "<BASE64_STRING>",
      "percentage_match": 64.7401,
      "claimed_doc_type": "citizenship-front",
      "detected_doc_type": "citizenship-front",
      "reason": "Valid"
    }
  ],
  "documentPhoto": [
    {
      "created_at": "2026-01-27 10:43:26.644142+00:00",
      "is_verified": true,
      "nationality": "nepali",
      "document_number": "11111111",
      "photo": "<BASE64_STRING>",
      "claimed_doc_type": "citizenship-back",
      "detected_doc_type": "citizenship-back",
      "reason": "Valid Type"
    }
  ],
  "gestureDetectionLog": [
    {
      "created_at": "2026-01-27 10:43:10.255518+00:00",
      "is_verified": true,
      "challenged_gesture": "Thumb_Down",
      "detected_gesture": "Thumb_Down",
      "percentage_match": 80.8998,
      "photo": "<BASE64_STRING_OF_GESTURE>",
      "reason": "Valid",
      "is_passive_live": true,
      "passive_score": 99.998
    }
  ],
  "faceDetectionLog": [
    {
      "created_at": "2026-01-27 10:42:58.538744+00:00",
      "is_verified": false,
      "photo": "<BASE64_STRING_OF_FACE>",
      "age": "-1",
      "gender": "N/A",
      "reason": "Face Occluded or Blurry.",
      "force_next": true
    }
  ],
  "nationality": "nepali",
  "completed_at": "2026-01-27T10:43:27.882837+00:00",
  "bypassed": 1,
  "document_uplaod_retries": 2,
  "session": "F7bgp2I",
  "faceDetectionSuccess": false,
  "document_number": "11111111",
  "gestureSuccess": true,
  "gender": "N/A",
  "documentDetectionSuccess": true,
  "in_progress": 0,
  "age": -1,
  "expires_at": "2026-01-29T18:24:26.141586+00:00",
  "userPhoto": "<BASE64_STRING_OF_USER>",
  "gesture_photo": "<BASE64_STRING>",
  "gesture_challenge": [
    "Thumb_Down"
  ],
  "percentage_match": 64.7401,
  "face_detection_retries": 1,
  "allow_force_next": 1,
  "started_at": "2026-01-27T10:42:46.141586+00:00",
  "gesture_verification_retries": 1,
  "label": "Jane User",
  "secondary_label": "jane",
  "identifier": "1715",
  "jwt": "<JWT_TOKEN>",
  "is_verified": true,
  "forced_next": false,
  "signature": "<SIGNATURE>"
}
  • Note: The photo, original_photo, userPhoto, and gesture_photo fields contain the full Base64 string of the respective images.

12. Generate KYC URL (SaaS with OCR)

This is the SaaS with OCR version of the KYC URL generation flow.

Use the same initialization flow as #11 for generating the JWT token, making the request, and handling remaining credits and error responses.

For the JWT payload:

  • If initiating on the web:

    • set "is_sdk": false

    • include "return_url": "https://yourapp.example.com/kyc/complete"

  • If initiating via Flutter SDK:

    • set "is_sdk": true

    • do not include return_url

12.1 Webhook Notification (Full Payload - SaaS with OCR)

When the KYC process is completed, the server sends a notification to the callback URL specified in the JWT payload. The SaaS + OCR flow returns a different payload shape (and includes additional OCR results).

  • Unicode rendering (Nepali): Some fields (e.g. issue_date) may be returned in Nepali/Devanagari Unicode (sometimes serialized as escapes like "\u0968\u0966..."). Clients should treat the payload as UTF-8 and render these characters as-is.

  • PII: The example below is redacted. Do not store or display raw PII (names, addresses, document numbers, IP addresses, JWTs, signatures) unless required and permitted by your compliance requirements.

  • Images (Base64): Any image fields are replaced with placeholders like <BASE64_IMAGE_REDACTED> to indicate they are Base64 strings.

{
    "ocr_image_results": [
      {
        "image_index": 0,
        "page_identifier": "citizenship-front",
        "page_title": "Citizenship Front Page",
        "selected_nationality": "nepali",
        "selected_document_type": "citizenship",
        "is_front_page": true,
        "is_photo_page": true,
        "detected_type": "citizenship",
        "normalized_document_type": "citizenship",
        "success": true,
        "found": true,
        "is_document_valid": true,
        "confidence": 0.9538843631744385,
        "error": null,
        "forgery_result": {
  
        },
        "forgery_checked": false,
        "is_forged": false,
        "forgery_decision": null,
        "heatmap_image": null,
        "forgery_error": null,
        "data": {
          "detected_type": "citizenship",
          "id_number": "<string — Devanagari numerals, format: DD-CC-PP-NNNNNNN>",
          "name": "<string — Devanagari script full name>",
          "address": "<string — Devanagari script, ward/municipality/district>",
          "dob": {
            "year": "<string — unicode>",
            "month": "<string — unicode>",
            "day": "<string — unicode>"
          },
          "gender": "<string — Devanagari: पुरुष | महिला | अन्य>",
          "fathers_name": "<string — Devanagari script>",
          "mothers_name": "<string — Devanagari script>",
          "place_of_issue": "<string — Devanagari script, district office name>"
        },
        "translations": {
          "en": {
            "detected_type": "citizenship",
            "id_number": "<string>",
            "name": "<string>",
            "address": "<string>",
            "gender": "<string>",
            "fathers_name": "<string>",
            "mothers_name": "<string>",
            "place_of_issue": "<string>",
            "dob": {
              "year": "2052",
              "month": "05",
              "day": "18"
            }
          }
        },
        "faces": [
          {
            "confidence": 0.9996335506439209,
            "facial_area": {
              "x_min": 61.21208190917969,
              "y_min": 239.77182006835938,
              "x_max": 158.7705535888672,
              "y_max": 337.3302917480469,
              "left_eye": [
                93,
                274
              ],
              "right_eye": [
                129,
                276
              ]
            }
          }
        ]
      },
      {
        "image_index": 1,
        "page_identifier": "citizenship-back",
        "page_title": "Citizenship Back Page",
        "selected_nationality": "nepali",
        "selected_document_type": "citizenship",
        "is_front_page": false,
        "is_photo_page": false,
        "detected_type": "citizenship-back",
        "normalized_document_type": "citizenship-back",
        "success": true,
        "found": true,
        "is_document_valid": true,
        "confidence": 0.9573695659637451,
        "error": null,
        "forgery_result": {
  
        },
        "forgery_checked": false,
        "is_forged": false,
        "forgery_decision": null,
        "heatmap_image": null,
        "forgery_error": null,
        "data": {
          "detected_type": "citizenship-back",
          "id_number": "<string>",
          "name": "<string>",
          "address": "<string>",
          "dob": {
            "year": "2050",
            "month": "09",
            "day": "12"
          },
          "gender": "<string>",
          "issue_date": "<string — unicode>",
          "issue_date_type": "BS"
        },
        "translations": null,
        "faces": []
      }
    ],
    "ocr_frames": [
      {
        "index": 0,
        "type": "citizenship-front",
        "title": "Citizenship Front Page",
        "image": "<image/jpeg>"
      },
      {
        "index": 1,
        "type": "citizenship-back",
        "title": "Citizenship Back Page",
        "image": "<image/jpeg>"
      }
    ],
    "gesture_verification_retries": 1,
    "expires_at": "2026-04-28T06:15:47.961877+00:00",
    "gender": "<string>",
    "ocr_summary": {
      "document_type": "citizenship",
      "selected_document_type": "citizenship",
      "selected_nationality": "nepali",
      "detected_document_type": "citizenship",
      "document_type_status": "Matched selected document type",
      "confidence": 0.9573695659637451,
      "is_document_valid": true,
      "found": true,
      "successful_images": 2,
      "uploaded_image_count": 2,
      "front_page_identifier": "citizenship-front",
      "forgery_detected": false,
      "forgery_checked_page_count": 0,
      "forged_page_count": 0,
      "forgery_decision": null,
      "page_results": [
        {
          "image_index": 0,
          "page_identifier": "citizenship-front",
          "page_title": "Citizenship Front Page",
          "selected_nationality": "nepali",
          "selected_document_type": "citizenship",
          "is_front_page": true,
          "is_photo_page": true,
          "detected_type": "citizenship",
          "normalized_document_type": "citizenship",
          "success": true,
          "found": true,
          "is_document_valid": true,
          "confidence": 0.9538843631744385,
          "error": null,
          "forgery_result": {
  
          },
          "forgery_checked": false,
          "is_forged": false,
          "forgery_decision": null,
          "heatmap_image": null,
          "forgery_error": null,
          "data": {
            "detected_type": "citizenship",
            "id_number": "<string — Devanagari numerals, format: DD-CC-PP-NNNNNNN>",
            "name": "<string — Devanagari script full name>",
            "address": "<string — Devanagari script, ward/municipality/district>",
            "dob": {
              "year": "<string — unicode>",
              "month": "<string — unicode>",
              "day": "<string — unicode>"
            },
            "gender": "<string — Devanagari: पुरुष | महिला | अन्य>",
            "fathers_name": "<string — Devanagari script>",
            "mothers_name": "<string — Devanagari script>",
            "place_of_issue": "<string — Devanagari script, district office name>"
          },
          "translations": {
            "en": {
              "detected_type": "citizenship",
              "id_number": "<string>",
              "name": "<string>",
              "address": "<string>",
              "gender": "<string>",
              "fathers_name": "<string>",
              "mothers_name": "<string>",
              "place_of_issue": "<string>",
              "dob": {
                "year": "2052",
                "month": "05",
                "day": "12"
              }
            }
          },
          "faces": [
            {
              "confidence": 0.9996335506439209,
              "facial_area": {
                "x_min": 61.21208190917969,
                "y_min": 239.77182006835938,
                "x_max": 158.7705535888672,
                "y_max": 337.3302917480469,
                "left_eye": [
                  93,
                  274
                ],
                "right_eye": [
                  129,
                  276
                ]
              }
            }
          ]
        },
        {
          "image_index": 1,
          "page_identifier": "citizenship-back",
          "page_title": "Citizenship Back Page",
          "selected_nationality": "nepali",
          "selected_document_type": "citizenship",
          "is_front_page": false,
          "is_photo_page": false,
          "detected_type": "citizenship-back",
          "normalized_document_type": "citizenship-back",
          "success": true,
          "found": true,
          "is_document_valid": true,
          "confidence": 0.9573695659637451,
          "error": null,
          "forgery_result": {
  
          },
          "forgery_checked": false,
          "is_forged": false,
          "forgery_decision": null,
          "heatmap_image": null,
          "forgery_error": null,
          "data": {
            "detected_type": "citizenship-back",
            "id_number": "<string>",
            "name": "<string>",
            "address": "<string>",
            "dob": {
              "year": "2050",
              "month": "09",
              "day": "12"
            },
            "gender": "<string>",
            "issue_date": "<string — unicode>",
            "issue_date_type": "BS"
          },
          "translations": null,
          "faces": []
        }
      ],
      "reviewed_document_type": "citizenship",
      "reviewed_field_count": 5,
      "face_match_page_identifier": "citizenship-front"
    },
    "ocr_extra_fields": {
      "fathers_name": "<string — Devanagari script>",
      "mothers_name": "<string — Devanagari script>",
      "place_of_issue": "<string — Devanagari script, district office name>",
      "issue_date": "<string — unicode>",
      "issue_date_type": "BS"
    },
    "gesture_photo": "<image/jpeg>",
    "ocr_data": {
      "detected_type": "citizenship",
      "id_number": "<string — Devanagari numerals, format: DD-CC-PP-NNNNNNN>",
      "name": "<string — Devanagari script full name>",
      "address": "<string — Devanagari script, ward/municipality/district>",
      "dob": {
        "year": "<string — unicode>",
        "month": "<string — unicode>",
        "day": "<string — unicode>"
      },
      "gender": "<string — Devanagari: पुरुष | महिला | अन्य>",
      "fathers_name": "<string — Devanagari script>",
      "mothers_name": "<string — Devanagari script>",
      "place_of_issue": "<string — Devanagari script, district office name>",
      "issue_date": "<string — unicode>",
      "issue_date_type": "BS"
    },
    "document_forgery_results": [],
    "userPhoto": "<image/jpeg>",
    "documentDetectionLog": [
      {
        "created_at": "2026-04-28T05:51:51.450412+00:00",
        "is_verified": true,
        "photo": "<image/jpeg>",
        "original_photo": "<image/jpeg>",
        "nationality": "nepali",
        "document_number": "<string — unicode>",
        "percentage_match": 46.615300000000005,
        "claimed_doc_type": "citizenship",
        "detected_doc_type": "citizenship",
        "reason": "Valid"
      }
    ],
    "session": "<string>",
    "gesture_challenge": [
      "Pointing_Up"
    ],
    "ocr_review_field_keys": [
      "id_number",
      "name",
      "address",
      "dob",
      "gender"
    ],
    "completed_at": "2026-04-28T05:51:56.347779+00:00",
    "document_forgery_summary": {
  
    },
    "percentage_match": 46.615300000000005,
    "ocr_primary_image": "<image/jpeg>",
    "ocr_review_fields_display": [
      {
        "key": "id_number",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "name",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "address",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "dob",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "gender",
        "label": "<string>",
        "value": "<string — unicode>"
      }
    ],
    "documentPhoto": [
      {
        "created_at": "2026-04-28T05:51:51.450412+00:00",
        "is_verified": true,
        "photo": "<image/jpeg>",
        "original_photo": "<image/jpeg>",
        "nationality": "nepali",
        "document_number": "<string — unicode>",
        "percentage_match": 46.615300000000005,
        "claimed_doc_type": "citizenship",
        "detected_doc_type": "citizenship",
        "reason": "Valid"
      }
    ],
    "document_number": "<string — unicode>",
    "in_progress": 0,
    "ocr_extra_fields_display": [
      {
        "key": "fathers_name",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "mothers_name",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "place_of_issue",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "issue_date",
        "label": "<string>",
        "value": "<string — unicode>"
      },
      {
        "key": "issue_date_type",
        "label": "<string>",
        "value": "BS"
      }
    ],
    "ocr_reviewed_fields": {
      "id_number": "<string — Devanagari numerals, format: DD-CC-PP-NNNNNNN>",
      "name": "<string — Devanagari script full name>",
      "address": "<string — Devanagari script, ward/municipality/district>",
      "dob": "<string — Devanagari numerals, BS date YYYY-MM-DD>",
      "gender": "<string — Devanagari: पुरुष | महिला | अन्य>"
    },
    "gestureSuccess": true,
    "ocr_document_type": "citizenship",
    "age": 32,
    "ocr_raw_results": [
      {
        "success": true,
        "found": true,
        "detected_type": "citizenship",
        "data": {
          "detected_type": "citizenship",
          "id_number": "<string — Devanagari numerals, format: DD-CC-PP-NNNNNNN>",
          "name": "<string — Devanagari script full name>",
          "address": "<string — Devanagari script, ward/municipality/district>",
          "dob": {
            "year": "<string — unicode>",
            "month": "<string — unicode>",
            "day": "<string — unicode>"
          },
          "gender": "<string — Devanagari: पुरुष | महिला | अन्य>",
          "fathers_name": "<string — Devanagari script>",
          "mothers_name": "<string — Devanagari script>",
          "place_of_issue": "<string — Devanagari script, district office name>"
        },
        "translations": {
          "en": {
            "detected_type": "citizenship",
            "id_number": "<string>",
            "name": "<string>",
            "address": "<string>",
            "gender": "<string>",
            "fathers_name": "<string>",
            "mothers_name": "<string>",
            "place_of_issue": "<string>",
            "dob": {
              "year": "2052",
              "month": "05",
              "day": "18"
            }
          }
        },
        "is_document_valid": true,
        "confidence": 0.9538843631744385,
        "error": null,
        "faces": [
          {
            "confidence": 0.9996335506439209,
            "facial_area": {
              "x_min": 61.21208190917969,
              "y_min": 239.77182006835938,
              "x_max": 158.7705535888672,
              "y_max": 337.3302917480469,
              "left_eye": [
                93,
                274
              ],
              "right_eye": [
                129,
                276
              ]
            }
          }
        ],
        "page_identifier": "citizenship-front",
        "page_title": "Citizenship Front Page",
        "selected_nationality": "nepali",
        "selected_document_type": "citizenship",
        "is_front_page": true,
        "is_photo_page": true
      },
      {
        "success": true,
        "found": true,
        "detected_type": "citizenship-back",
        "data": {
          "detected_type": "citizenship-back",
          "id_number": "<string>",
          "name": "<string>",
          "address": "<string>",
          "dob": {
            "year": "2050",
            "month": "09",
            "day": "12"
          },
          "gender": "<string>",
          "issue_date": "<string — unicode>",
          "issue_date_type": "BS"
        },
        "translations": null,
        "is_document_valid": true,
        "confidence": 0.9573695659637451,
        "error": null,
        "faces": [],
        "page_identifier": "citizenship-back",
        "page_title": "Citizenship Back Page",
        "selected_nationality": "nepali",
        "selected_document_type": "citizenship",
        "is_front_page": false,
        "is_photo_page": false
      }
    ],
    "faceDetectionSuccess": true,
    "faceDetectionLog": [
      {
        "created_at": "2026-04-28 05:50:57.985303+00:00",
        "is_verified": true,
        "age": 32,
        "gender": "<string>",
        "photo": "<image/jpeg>",
        "reason": "Face Attributes Clearly Visible."
      }
    ],
    "ocr_face_match_page_identifier": "citizenship-front",
    "documentDetectionSuccess": true,
    "face_detection_retries": 1,
    "_access_session_id": 16,
    "ocr_document_face_image": "<string>",
    "nationality": "nepali",
    "ocr_selected_nationality": "nepali",
    "document_upload_with_ocr_retries": 1,
    "ocr_detected_document_type": "citizenship",
    "ocr_selected_document_type": "citizenship",
    "gestureDetectionLog": [
      {
        "created_at": "2026-04-28 05:51:13.332434+00:00",
        "is_verified": true,
        "challenged_gesture": "Pointing_Up",
        "detected_gesture": "Pointing_Up",
        "percentage_match": 82.0312,
        "photo": "<image/jpeg>",
        "reason": "Valid",
        "is_passive_live": true,
        "passive_score": 99.92410242557526
      }
    ],
    "ocr_face_match_image": "<image/jpeg>",
    "started_at": "2026-04-28T05:50:47.961877+00:00",
    "client_ip": "157.119.70.92",
    "label": "<string>",
    "secondary_label": "<string>",
    "identifier": "<string>",
    "jwt": "<string>",
    "is_verified": true,
    "forced_next": false,
    "signature": "<string>"
  }

13. KYB - Business Document Detection

Set of endpoints for detecting and validating business-related documents.

13.1 Single Inference

Detects business document class in a single uploaded image.

  • Method: POST

  • Endpoint: /api/v1/business_doc_detection/inference/single

  • Content-Type: multipart/form-data

Parameters

Key

Type

Description

file expected_class confidence

File Text Number

Required. The image file to analyze. Optional. The expected class name for validaton. Optional. Confidence threshold. Default: 0.7

Response (200 OK)

{
  "filename": "image.jpg",
  "predicted_class": "business_vat_pan",
  "expected_class": "business_vat_pan",
  "confidence": 0.95,
  "is_correct": true,
  "bbox": [100, 150, 400, 500],
  "output_path": "/app/media_files/results/image.jpg"
}

13.2 Folder Inference

Batch processes images within a specified folder path.

  • Method: POST

  • Endpoint: /api/v1/business_doc_detection/inference/folder

  • Content-Type: multipart/form-data

Parameters

Key

Type

Description

folder_path confidence

Text Number

Required. Path to the folder containing imgs Optional. Confidence threshold. Default: 0.7

Response (200 OK)

{
  "total_images": 10,
  "correct_predictions": 8,
  "incorrect_predictions": 1,
  "no_predictions": 1,
  "files": [
     { "filename": "doc1.jpg", "predicted_class": "vat", "confidence": 0.98 },
     { "filename": "doc2.jpg", "predicted_class": "pan", "confidence": 0.92 }
  ]
}

13.3 Health Check (KYB)

Checks the status of the Business Document Detection service.

  • Method: GET

  • Endpoint: /api/v1/business_doc_detection/health

Response (200 OK)

{ "status": "Ok" }

Security & Compliance

  • Transport Security — All traffic must use HTTPS (TLS 1.2+). Plain HTTP requests are rejected.

  • Transient Processing — Face and document data are processed transiently. No images are stored unless explicitly configured for audit logging.

  • Privacy Compliance — ThirdFactor.ai is mostly compliant with major privacy frameworks, including:

    • GDPR (General Data Protection Regulation)

  • Token Confidentiality — API Bearer tokens must be kept confidential and must never be exposed in client-side code or public repositories.