Verification

Python server SDK

thirdfactor-sdk — create verification sessions, retrieve decisions, manage risk lists, and verify signed webhooks from Python.

The official Python SDK is a server-only client for the ThirdFactor Verify and Partner APIs. The PyPI distribution is thirdfactor-sdk; Python code imports it as thirdfactor.

Warning

Keep your tenant API key on the server. Never put it in browser code, a mobile application, or a public repository.

Requirements

  • Python 3.9 or newer
  • No runtime dependencies
  • A tenant API key from Console → Settings → API keys

Installation

pip install thirdfactor-sdk

Create a session

import os

from thirdfactor import ThirdFactor

tf = ThirdFactor(
    api_key=os.environ["THIRDFACTOR_API_KEY"],
    base_url="https://your-tenant.thirdfactor.ai",
    timeout=15,
)

session = tf.sessions.create(
    vendor_data="user-42",
    workflow_id="4c615aec-e173-450d-8089-30d4edc835f3",
    callback_url="https://app.example.com/kyc/done",
    contact_email="[email protected]",
    idempotency_key="kyc-user-42",
)

print(session["id"])
print(session["url"])

Persist the session id and send only its hosted url to the applicant. Use a stable idempotency key for each logical attempt so a retry returns the original session without charging twice.

Select a workflow

List the workflows available to the API key's tenant:

workflows = tf.request("GET", "/v3/workflows/")

for workflow in workflows:
    print(workflow["id"], workflow["name"], workflow["status"])

Pass one of those IDs as workflow_id when creating the session. Omit it to use the tenant's default workflow. Existing sessions retain their frozen workflow snapshot; workflow edits affect newly created sessions.

Retrieve a session or decision

session = tf.sessions.retrieve(session_id)
decision = tf.sessions.decision(session_id)

if decision["decision"] == "approved":
    grant_access()

The hosted UI result is advisory. Grant access, move money, or provision an account only after a signed webhook or this authenticated decision lookup.

Verify webhooks

Pass the untouched request bytes and the X-Webhook-Signature header before parsing JSON:

import os

from thirdfactor import SignatureError

try:
    event = tf.webhooks.construct_event(
        raw_body,
        signature_header,
        os.environ["THIRDFACTOR_WEBHOOK_SECRET"],
    )
except SignatureError:
    # Reject invalid, malformed, or stale deliveries.
    raise

The verifier uses constant-time HMAC comparison and a five-minute replay window by default. See webhook signatures for the raw-body requirements.

Handle API errors

from thirdfactor import APIError

try:
    session = tf.sessions.retrieve(session_id)
except APIError as error:
    print(error.status)      # HTTP status
    print(error.body)        # parsed API response
    print(error.request_id)  # support correlation ID, when present

Resources