{
  "info": {
    "_postman_id": "5c1f7a9e-2f64-4b3a-9d1c-8e0a6b21c4d7",
    "name": "Neetix Liveliness API",
    "description": "Selfie-KYC verification suite — face match, liveness, active sessions, 1:N face search, document MRZ, identity/contact validation, KYB, AML screening, workflow orchestration and prepaid billing.\n\nSetup: run `Signup (get API keys)` once with your email — it returns a live key (`lv_…`) and a free unmetered test key (`lv_test_…`), each shown only once. Put one of them into the `api_key` collection variable; every other request sends it as `Authorization: Bearer {{api_key}}`.\n\nBase URL defaults to the hosted deployment; point `baseUrl` at your own host when self-hosting (default port :8090).\n\nFull docs: https://liveliness.neetix.in/developers/ · Interactive reference: https://liveliness.neetix.in/api-reference/",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://liveliness.neetix.in",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "session_id",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Getting started",
      "item": [
        {
          "name": "Signup (get API keys)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Store the live key for the rest of the collection (shown only once).",
                  "const body = pm.response.json();",
                  "if (body && body.api_key) {",
                  "    pm.collectionVariables.set('api_key', body.api_key);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "auth": {
              "type": "noauth"
            },
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"you@company.com\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/signup",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "signup"]
            },
            "description": "Public, per-IP rate limited (5/hour). Issues TWO keys in one call — `api_key` (`lv_…`, live, 1,000 free credits) and `test_api_key` (`lv_test_…`, free and unmetered, isolated client_id). Each key is shown only once; the test script saves `api_key` into the collection variable."
          }
        }
      ]
    },
    {
      "name": "Face verification",
      "item": [
        {
          "name": "Face match + liveliness",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "person",
                  "type": "file",
                  "src": [],
                  "description": "The selfie (required). Max 5 MB."
                },
                {
                  "key": "card",
                  "type": "file",
                  "src": [],
                  "description": "The ID / reference photo (required). Max 5 MB."
                },
                {
                  "key": "customer_id",
                  "value": "cust_123",
                  "type": "text",
                  "disabled": true,
                  "description": "Optional string."
                },
                {
                  "key": "client_ref_id",
                  "value": "postman-demo-001",
                  "type": "text",
                  "disabled": true,
                  "description": "Optional string."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/face/face-match",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "face", "face-match"]
            },
            "description": "1:1 face match + passive liveliness in one call (2 credits). Returns `verdict` (approved | review | declined), `warnings[]`, and `result` with `is_same_face`, `same_face_confidence`, `liveness_score`, quality and forensics signals. Optional injection-defense fields (`capture_nonce`, `client_signature`, `attest_*`) are documented in INTEGRATION.md §4."
          }
        },
        {
          "name": "Passive liveliness (standalone)",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "person",
                  "type": "file",
                  "src": [],
                  "description": "The selfie (required)."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/liveness",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "liveness"]
            },
            "description": "Passive presentation-attack detection on a single selfie (1 credit). Returns `status` (\"Approved\" | \"Declined\" | \"Not Finished\"), `liveness_score`, `liveness_status`."
          }
        }
      ]
    },
    {
      "name": "Face gallery (1:N)",
      "item": [
        {
          "name": "Enroll face",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "subject_id",
                  "value": "subject-001",
                  "type": "text",
                  "description": "Your identifier for this face (required)."
                },
                {
                  "key": "person",
                  "type": "file",
                  "src": [],
                  "description": "Face image to enroll (required)."
                },
                {
                  "key": "blocklisted",
                  "value": "true",
                  "type": "text",
                  "disabled": true,
                  "description": "Optional — enroll into the blocklist."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/face/enroll",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "face", "enroll"]
            },
            "description": "Adds a face to your tenant's gallery for 1:N search (dedupe / blocklist). Test keys enroll into an isolated gallery."
          }
        },
        {
          "name": "Search faces",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "person",
                  "type": "file",
                  "src": [],
                  "description": "Probe face image (required)."
                },
                {
                  "key": "top_k",
                  "value": "5",
                  "type": "text",
                  "disabled": true,
                  "description": "Optional — max matches to return."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/face/search",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "face", "search"]
            },
            "description": "1:N search across your enrolled gallery."
          }
        }
      ]
    },
    {
      "name": "Active liveliness sessions",
      "item": [
        {
          "name": "Start session",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Save the session id for the verify request.",
                  "const body = pm.response.json();",
                  "if (body && body.session_id) {",
                  "    pm.collectionVariables.set('session_id', body.session_id);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "url": {
              "raw": "{{baseUrl}}/v1/session/start",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "session", "start"]
            },
            "description": "Issues a randomized ordered challenge list (`center` | `left` | `right` | `blink`). Free — the charge lands on verify. Sessions expire after 10 minutes. The test script saves `session_id`."
          }
        },
        {
          "name": "Verify session frames",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "frame_0",
                  "type": "file",
                  "src": [],
                  "description": "Frame answering challenges[0]."
                },
                {
                  "key": "frame_1",
                  "type": "file",
                  "src": [],
                  "description": "Frame answering challenges[1]."
                },
                {
                  "key": "frame_2",
                  "type": "file",
                  "src": [],
                  "description": "Frame answering challenges[2] (one frame per challenge)."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/session/{{session_id}}/verify",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "session", "{{session_id}}", "verify"]
            },
            "description": "Upload one frame per challenge as `frame_0`, `frame_1`, … (2 credits). Single-use — an already-verified or expired session answers 400."
          }
        }
      ]
    },
    {
      "name": "Documents & validation",
      "item": [
        {
          "name": "Parse document MRZ",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"mrz\": \"P<UTOERIKSSON<<ANNA<MARIA<<<<<<<<<<<<<<<<<<<\\nL898902C36UTO7408122F1204159ZE184226B<<<<<10\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/document/mrz",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "document", "mrz"]
            },
            "description": "Parses and check-digit-validates a passport / ID machine-readable zone (2 or 3 MRZ lines, joined with \\n). The example body is the ICAO 9303 specimen passport MRZ."
          }
        },
        {
          "name": "Validate identity numbers",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"aadhaar\": \"<12-digit aadhaar>\",\n  \"pan\": \"<10-char PAN>\",\n  \"voter\": \"<voter id>\",\n  \"dl\": \"<driving licence>\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/validate/identity",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "validate", "identity"]
            },
            "description": "All fields optional — send any subset. Returns per-field results, e.g. `fields.aadhaar.{valid, masked}`, `fields.pan.entity_type`."
          }
        },
        {
          "name": "Validate contact details",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"someone@example.com\",\n  \"phone\": \"+919876543210\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/validate/contact",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "validate", "contact"]
            },
            "description": "Both fields optional. Returns `fields.email.{valid, is_disposable}` and `fields.phone.{normalized, is_mobile}`."
          }
        },
        {
          "name": "KYB — validate business identifiers",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"gstin\": \"<15-char GSTIN>\",\n  \"pan\": \"<10-char PAN>\",\n  \"cin\": \"<21-char CIN>\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/kyb/validate",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "kyb", "validate"]
            },
            "description": "All fields optional — send any subset. Per-field `{ valid, …decoded }` (GSTIN checksum, state, embedded PAN)."
          }
        }
      ]
    },
    {
      "name": "AML",
      "item": [
        {
          "name": "Screen a name",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"John Doe\",\n  \"dob\": \"1980-01-01\",\n  \"threshold\": 0.85\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/v1/aml/screen",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "aml", "screen"]
            },
            "description": "Sanctions/watchlist screening (1 credit). `dob` and `threshold` are optional. Returns `{ hit, screened_against, matches: [{ matched_name, score, list, program, dob_match }] }`."
          }
        }
      ]
    },
    {
      "name": "Workflows",
      "item": [
        {
          "name": "Run workflow (multi-check)",
          "request": {
            "method": "POST",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "checks",
                  "value": "liveness,face_match,aml",
                  "type": "text",
                  "description": "Required comma list from: liveness, face_match, mrz, aml, device."
                },
                {
                  "key": "person",
                  "type": "file",
                  "src": [],
                  "description": "Selfie (liveness / face_match)."
                },
                {
                  "key": "card",
                  "type": "file",
                  "src": [],
                  "description": "ID image (face_match)."
                },
                {
                  "key": "name",
                  "value": "John Doe",
                  "type": "text",
                  "description": "Applicant name (aml check)."
                },
                {
                  "key": "dob",
                  "value": "1980-01-01",
                  "type": "text",
                  "description": "Applicant DOB (aml check)."
                },
                {
                  "key": "mrz",
                  "value": "",
                  "type": "text",
                  "disabled": true,
                  "description": "MRZ text (mrz check)."
                },
                {
                  "key": "device",
                  "value": "",
                  "type": "text",
                  "disabled": true,
                  "description": "Device/IP signals as a JSON string (device check)."
                }
              ]
            },
            "url": {
              "raw": "{{baseUrl}}/v1/workflow/run",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "workflow", "run"]
            },
            "description": "One call, many checks (3 credits). Runs the requested checks and folds them into a single `verdict`: approved | review | declined, with per-check detail under `checks`."
          }
        }
      ]
    },
    {
      "name": "Billing",
      "item": [
        {
          "name": "Balance",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{baseUrl}}/v1/billing/balance",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "billing", "balance"]
            },
            "description": "Current prepaid credit balance: `{ balance, metered }`. Test keys report `metered: false` with a synthetic balance. An exhausted balance makes billable calls answer 402 `insufficient_credits`."
          }
        },
        {
          "name": "Ledger",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{baseUrl}}/v1/billing/ledger?limit=50",
              "host": ["{{baseUrl}}"],
              "path": ["v1", "billing", "ledger"],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Max entries (default 50)."
                }
              ]
            },
            "description": "Credit movements, newest first: `{ balance, entries: [{ delta, balance_after, reason, ref_id, created_at }] }`. Reasons include `charge:face_match`, `signup_bonus`, `topup:dodo`, `admin_grant`."
          }
        }
      ]
    }
  ]
}
