Reference

Changelog

Notable changes to the ThirdFactor Obsidian API, SDKs, and hosted flows.

Dated, most-recent-first. Breaking changes are called out explicitly; when in doubt, pin workflow_id and branch on stable decisions rather than raw statuses.

How to read this changelog

Scan the headline

Each entry opens with what changed and why it matters, before the field-level detail. If nothing in the headline touches your integration, you can usually skip the rest of the entry.

Check for a breaking-change callout

A <Warning> in an entry means existing integrations need action — a payload shape changed, a field was removed, or a default behavior flipped. An entry with no warning is additive: new capability, nothing to change on your side.

Cross-reference the linked pages

Entries link to the concept/reference page that now documents the feature in full, rather than duplicating the whole spec inline here. Use the changelog to find out that something changed, and the linked page to find out how it works.

2026-07-11 — ThirdFactor Verify SDKs and NFC

The big one: ThirdFactor Verify — a built-in KYC engine — and a set of native client SDKs, so no external verification SDK is required.

ThirdFactor Verify engine (/v3). Document verification, passive / colour-flash / 3D-action liveness, and face match run inside Obsidian. Design workflows in Console → Config → KYC Workflows; manage sessions and identities in Console → Verifications and Console → Identities.

  • POST /v3/session/ creates a hosted verification session and returns a url on the tenant flow domain. The server enforces the configured liveness method — it cannot be downgraded client-side.
  • Idempotency-Key on session create makes retries safe and never double-charges credits.
  • Read and manage sessions: GET /v3/session/, GET /v3/session/<id>/, GET /v3/session/<id>/decision/, plus update-status, delete, logs, checklist, tags, and generate-pdf.
  • Standalone tools mirror the console Manual Tools: aml-check, face-search, signature-verify, signature-search (beta), signature-enroll, and document-extract.

Client SDKs. Native SDKs that open the flow and return an advisory result:

NFC. Native NFC reader modules on iOS, Android, and Flutter read the document chip; a bidirectional bridge exposes capability/command negotiation, and the backend accepts chip data via an NFC flow step. See the NFC deep-dive.

KYC webhooks. Terminal sessions emit signed webhook events — identity.kyc.session.approved, .declined, .review, .expired — through the same signed delivery pipeline as application events.

Warning

KYC session webhook payloads are flat: decision, status, vendor_data, session_id, and the rest are top-level fields, with no nested session object. Application webhooks keep the versioned { payload_version, application, form_data, sdk_response, blocklist_match } envelope. If you built a webhook handler before this release that assumed every event had a nested application object, it needs a branch on event_type to route KYC session events differently. See webhooks.

Hosted flows. A hosted session whose flow contains an sdk step runs ThirdFactor Verify inline as a single continuous flow — no external verification vendor and no hand-off out of the flow.

Info

This is the starting point for the public changelog. Subsequent releases will be added here, newest first, with any breaking changes flagged.

Versioning and stability

Obsidian's public contract is layered so that additive changes never break a well-written integration:

  • Stable decisions (approved, rejected / declined, manual_review / in_review, in_progress, abandoned) are the long-term contract. New raw statuses can appear for workflow diagnostics without changing this set — see decisions.
  • workflow_id pins which modules a session runs. Leaving it unset uses the tenant default, which an operator can change in the console at any time — pin it explicitly if your integration depends on a specific module set.
  • Webhook envelopes are additive-only: new fields can appear, but existing fields keep their meaning. The payload_version on application events exists specifically so a schema change, if one is ever needed, is detectable rather than silent.
  • Unknown values are treated conservatively. An unrecognised terminal status should be handled the same way the SDKs handle it internally: as in_review, not as a pass. That one rule keeps forward-compatible code working across additive releases without a docs update on your side.

FAQ