Identity verification API webhook: persist state before waiting

Xây dựng tích hợp trong sandbox miễn phí trước khi chuẩn bị môi trường sản xuất.

Lựa chọn thống kê của bạn được dùng lại trên website và có thể tắt. Liên kết tài khoản cần đồng ý riêng.

Identity verification API webhook: persist state before waiting

Your onboarding service creates a hosted verification session and then waits for a webhook. Two things can go wrong while it waits: the process restarts, or the callback never arrives. If pending state lives only in memory, a restart loses it. If nothing enforces a deadline, a missing callback leaves the user stuck, or someone is tempted to treat silence as success. This article walks through the checked local restart and missing-callback branches of the synthetic verification_delivery example, shows the exact fixture outputs, and helps you decide whether a sandbox integration fits your task. The fixture accepts only synthetic callbacks and expires sessions locally; it never polls a provider.

Bài này hiện bằng tiếng Anh; bản dịch đang chờ cập nhật.

curl https://gridzen.ai/console/api/quickstart/trial \
  -H 'Content-Type: application/json' \
  -d '{"task": "identity_onboarding", "scenario": "success"}'

Hướng dẫn tích hợp

The problem and the decision

An identity verification API webhook is an asynchronous promise: the provider will report the outcome later. Your application owns everything that happens before then. The decision is concrete: where does pending state live, what deadline applies, and what happens when the deadline passes with no callback? The guide's rule is short. Persist pending state and a deadline. Recover with bounded retries, an authorized status refresh or human review. Never turn a missing callback into approval. The downloadable example demonstrates the persistence and local expiry parts of that rule. It does not demonstrate provider signature validation or status reconciliation, which a production implementation needs separately.

What the fixture actually implements

The example stores sessions in SQLite. Calling create writes a row with status pending and a deadline equal to now plus timeout; with the defaults that is 0 plus 60, so deadline is 60. Identifiers must start with fixture-, and the returned hosted_link points to an invalid example domain with link_executable false. The event method accepts only mode synthetic_fixture and source fixture_callback; anything else raises PRODUCTION_SIGNATURE_VERIFIER_NOT_IMPLEMENTED. The recover method marks a session expired when its deadline is less than or equal to the supplied time and its status is still pending, review or unknown. It returns provider_polled false: recovery is a local clock comparison, not a provider query. Any permission recorded here is a local fixture flag; live_permission_changed is always false, and synthetic fixture permission is never live business permission.

Worked hypothetical scenario: restart, then silence

Hypothetically, a seller starts onboarding at time 0. Your service calls create, gets session fixture-session, and stores it as pending with deadline 60. At time 20 the process restarts. Because state is in SQLite, the restarted process opens the same database file and calls read. The expected output still shows status pending, deadline 60, permission_granted false and grant_count 0; no new session is needed, and creating fixture-session again would fail on the primary key, which is your signal to resume rather than duplicate. No callback arrives. At time 61 a scheduled job calls recover. Expected fixture output: mode synthetic_fixture, session fixture-session, status expired, deadline 60, permission_granted false, grant_count 0, live_permission_changed false, policy_version 1, allow_action true, next review_or_authorized_provider_refresh, provider_polled false. Note that allow_action true only describes the session's policy setting; it grants nothing. If a late synthetic Approved event arrives after expiry, the session stays expired.

Failure handling your application still owns

The fixture returns a next action; it does not perform it. After expiry, your proposed design must choose between human review and an authorized status refresh against the real provider, with bounded attempts and a recorded outcome. Keep these failures distinct. An event for a session that does not match its tenant and subject raises BINDING_MISMATCH; treat that as a routing or security concern, not a decline. A read for an unknown session raises SESSION_NOT_FOUND; do not silently recreate it. A duplicate event returns the current state without granting again. Never interpret an expired status as declined for the person, and never as approved. In production, signature validation, provider reconciliation and customer permission rules remain separate work; this example does not establish them, and a full live hosted journey by a new person remains untested.

How to run the checked branches

Download the example, extract it and enter the verification_delivery directory. It needs Python 3.10 or newer, no credentials and no network. The guide names two targeted tests, test_restart and test_timeout_recovery in test_delivery.DeliveryTests, plus the full test_delivery suite covering simulated transitions, bindings, duplicate callbacks, restart and timeouts. The guide also shows a local recover request against a loopback address; that separate anonymous HTTP trial is not the same thing as the downloadable branches, and neither queries a provider. Passing tests show the local code handles these states. They do not prove production success or adoption, and live route availability requires separate confirmation.

Acceptance checklist

Before deciding a sandbox integration fits your task, confirm each item. Pending sessions are written to durable storage with a deadline before you send any link. A restarted process resumes the same session from the same database instead of creating a duplicate. A scheduled recovery job compares deadline with the current time and moves stale pending, review or unknown sessions to expired. The expired output carries provider_polled false in the fixture, and your real refresh path is authorized and bounded. A missing callback never produces permission_granted true. Late, duplicate and mismatched events are handled without new grants. Signature validation and provider reconciliation are listed as open production work. If those items match your needs, run the synthetic tests first, then consider saving an optional sandbox request.

Run the checked synthetic example

Download and extract https://gridzen.ai/downloads/verification-delivery.zip, enter verification_delivery, then run with Python 3.10+. This local example makes no network calls. Use a fresh database for an independent identity run.

python3 delivery.py identity --db /tmp/gridzen-article-fixture.sqlite

Sources and scope

https://gridzen.ai/guides/missing-verification-webhook/ https://gridzen.ai/guides/current-capabilities/ Based on the checked source snapshot and local fixture; proposed application rules are design advice, not proven production behavior. Written with AI assistance and reviewed independently.

Thử riêng ba kết quả sandbox Tạo tài khoản để tiếp tục tích hợp

Tải xuống không chứng minh đã chạy thành công. Ví dụ cục bộ và sandbox trực tuyến được thử riêng.

Kết nối ứng dụng

Chạy ba kết quả dữ liệu mẫu · Nhận hỗ trợ tích hợp

Kết nối tài khoản sandbox miễn phí

Tính hợp lệ cơ bản của số không chứng minh quyền kiểm soát hay khả năng liên lạc và không gửi OTP. Ứng dụng của bạn chịu trách nhiệm quyết định tiếp nhận.