Your onboarding service created a hosted verification session, stored it as pending, and the webhook never arrived. You must decide what the session becomes and what happens next. This article uses the checked local example: SQLite persistence, a deadline, and a recover step that expires the session locally. It never queries a provider, and a missing callback never becomes approval.
The problem: a pending session with no callback
A seller starts hosted identity verification. Your service writes a pending session with a deadline and waits. The callback may be lost, delayed or blocked by a misconfigured endpoint. If nothing acts on the deadline, the session stays pending forever. The user is stuck and your support team has no clear state to read. The tempting shortcuts are to approve after a while or to silently reject. Both turn missing evidence into a decision. Your real choice is narrower: when the deadline passes, move the session to a terminal state that means no answer arrived, then route the next action to review or to an authorized status refresh that your own integration owns.
What the local example actually implements
The downloadable example is a dependency-free Python 3.10+ fixture that needs no credentials or network. The Identity class stores sessions in SQLite with the fields status, deadline, granted and grants, plus policy_version and allow_action. create accepts only identifiers beginning with fixture- and a timeout between 1 and 3600 seconds, and writes status pending with deadline equal to now plus timeout. recover takes a session and the current time. If deadline is less than or equal to now and status is pending, review or unknown, it sets status to expired. It then returns the read result plus next set to review_or_authorized_provider_refresh and provider_polled set to false. That flag is literal: recover does not call any provider. Events accept only mode synthetic_fixture and source fixture_callback; anything else raises PRODUCTION_SIGNATURE_VERIFIER_NOT_IMPLEMENTED. There is no real signature verification. This is separate from the anonymous three-scenario HTTP trial and from the four-branch phone example.
Hypothetical scenario and expected fixture outputs
Hypothetical: a synthetic seller session fixture-session is created at time 0 with the default 60-second timeout, so deadline is 60. No callback arrives. Your scheduler, which you would build, calls recover at time 61. The tested output is: 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. Because state lives in SQLite, restarting the process against the same database file and calling recover gives the same result. If a late fixture Approved event arrives after the deadline, the event handler records it and keeps the session expired; it grants nothing. allow_action true only means local policy would allow an action; it is not a grant.
Failure handling your application owns
Proposed design, not implemented behavior: run recover from a durable scheduler, not from the request that created the session. Treat expired as no answer, not as declined, and show the user a retry path. If you have an authorized provider route, a bounded status refresh may follow, with signature validation and reconciliation specific to that provider; the example establishes neither. Errors in the fixture are explicit: reading an unknown session raises SESSION_NOT_FOUND, and an event for an unknown session or with the wrong tenant or subject raises BINDING_MISMATCH. Duplicate events are recorded by event id and return the current state without a second grant. Log these codes rather than retrying blindly.
Limits to keep in view
The fixture proves local state transitions only. It does not show that a real person completed a hosted journey, that a provider callback was signed, or that any live permission changed. Synthetic permission_granted is a local record, never real business permission. The hosted_link points to an invalid example domain and link_executable is false. Engineering tests cover transitions, bindings, duplicates, restart and timeouts; they are not evidence of production success or adoption. Live route availability needs separate confirmation.
Acceptance checklist
Run the restart and timeout recovery tests and confirm they pass. Create a session, restart, and confirm status is still pending with the same deadline. Call recover after the deadline and confirm status expired, permission_granted false and provider_polled false. Send a late synthetic Approved and confirm no grant. Confirm unknown sessions raise SESSION_NOT_FOUND or BINDING_MISMATCH. Confirm your design never maps expired to approval. Write down which future component will own signature validation and authorized refresh before you request a sandbox integration.
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.
curl https://gridzen.ai/console/api/quickstart/trial \
-H 'Content-Type: application/json' \
-d '{"task": "identity_onboarding", "scenario": "success"}'
This is synthetic integration testing, not identity verification or production authorization. Real payments are disabled.
Create a free sandbox account ยท Integration guide
Written and tested by the GridZen team with AI assistance.
Top comments (0)