KYC API integration: what an Approved result leaves to your application

Build your integration in the free sandbox before preparing for production.

Your measurement choice is reused on this site and can be turned off. Account association requires separate consent.

KYC API integration: what an Approved result leaves to your application

A KYC API can tell you a verification session ended as Approved. It cannot tell your application whether that session belongs to the tenant and user now asking for access, whether your business rule allows the action, or whether this callback was already processed. This article uses the checked synthetic example to show three caller-owned duties: binding the result, applying an explicit rule, and handling events idempotently. Everything shown runs locally with synthetic identifiers; it grants only fixture records, never real permissions.

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

Integration guide

The problem: Approved arrives, and someone wants to publish

Picture a small B2B marketplace. A new seller finishes hosted identity onboarding, the provider reports Approved, and the tempting handler flips a publish flag in the same step. That shortcut merges three questions: did verification pass, is this result about the right account, and does your policy allow the action now. The decision you face as an integrator is where each answer lives. The guide's position is direct: bind the verified event to the tenant, user and session, then apply the customer policy. Approved alone is not permission to publish. The checked example lets you test that separation locally before deciding whether a sandbox integration fits your task.

What the checked example implements

The downloadable example persists fixture sessions in SQLite. A session row stores tenant, subject, status, deadline, granted, grants, policy_version and allow_action. The event function accepts only mode synthetic_fixture and source fixture_callback; anything else raises PRODUCTION_SIGNATURE_VERIFIER_NOT_IMPLEMENTED, because there is no production signature verifier. Event identifiers must start with fixture-. A grant happens only when status is Approved, the caller passes policy as exactly True, and allow_action is set. Each processed event is recorded by session and event ID, so a replay returns current state without changing it. The read output always reports live_permission_changed false. The recover function marks overdue pending, review or unknown sessions as expired locally and reports provider_polled false: it never contacts a provider.

A worked hypothetical scenario with expected outputs

Hypothetical: fixture-tenant onboards fixture-user in fixture-session with a 60-second timeout. Creation returns state simulated, link_executable false and next send_real_provider_link_only_after_authorization; the hosted_link points to an invalid example domain and collects no ID. An Approved fixture event with policy True returns status approved, deadline 60, permission_granted true, grant_count 1, policy_version 1, allow_action true. Sending the same event ID again returns the identical record: grant_count stays 1. A later Declined event, as a correction, returns status declined, permission_granted false, grant_count 1; the count records history, while the flag reflects current access. In a separate session left pending past its deadline, recover returns status expired, permission_granted false, grant_count 0, next review_or_authorized_provider_refresh and provider_polled false.

Failure handling the caller owns

Wrong binding: an event naming a tenant or subject that does not match the stored row, or an unknown session, raises BINDING_MISMATCH; reading an unknown session raises SESSION_NOT_FOUND. Missing policy: an Approved event without policy True records approved status but grants nothing, which keeps verification and permission apart. Late events: once the deadline passes, the event marks the session expired rather than granting. Unrecognized statuses become unknown. Policy changes use revise_policy with an expected version; a mismatch raises STALE_POLICY_VERSION and a successful revision clears granted. Explicit re-grants go through decide, which requires current approved evidence, an unexpired deadline, allow_action and approve True, otherwise raising CURRENT_EVIDENCE_AND_EXPLICIT_APPROVAL_REQUIRED. In your proposed application design, map each of these to a reviewed queue, not a silent pass or reject.

Proposed design versus implemented behavior

Implemented: the fixture logic above, its SQLite persistence and its unit tests covering simulated transitions, bindings, duplicates, restart and timeouts. Proposed, for your application: a real signed-callback verifier through an authorized adapter, a policy store your team owns, and an audit trail linking each grant to an event ID and policy version. The GridZen production description says signed notifications are verified and authoritative decisions re-fetched, while customer permissions require the customer's integration and rules; end-to-end live customer action remains unverified, and a new person passing the full hosted journey remains untested. Synthetic fixture permission is not live business permission, and passing tests do not prove production success.

Acceptance checklist before a sandbox request

Confirm you can show: a mismatched tenant or subject yields BINDING_MISMATCH; Approved without policy True leaves permission_granted false; a duplicate event leaves grant_count unchanged; a correction to Declined sets permission_granted false; a late event or recover produces expired with provider_polled false; a stale policy version is rejected; every output shows live_permission_changed false. If each holds and your team can name who owns the policy and the signature verifier, an optional saved sandbox request is a reasonable next step. If not, keep iterating locally; the fixture is the cheaper place to find gaps.

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/approved-seller-permissions/ 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.

Separately try three sandbox outcomes Create an account to continue integrating

A download does not prove a successful run. Local examples and the online sandbox are tested separately.

Connect your app

Run three synthetic outcomes · Get integration help

Connect a free sandbox account

Basic number validity does not prove possession or reachability and does not send OTP. Your app owns the admission decision.