KYC (Identity Verification)
Overview
KYC (Know Your Customer) is an identity verification process required during Installment Loan onboarding. The Transactions Service integrates with Plaid Identity Verification to manage KYC sessions. The app calls the user-service for KYC interactions, and the user-service proxies the calls through to transaction-service. This is because transactions-service is the only service that has access to the Plaid API, and it would not make sense in a service domain sense to have the app call transaction-service directly for KYC interactions.
A KYC session tracks a user through a series of verification steps (document upload, selfie check, watchlist screening, etc.). The session status is updated asynchronously via Plaid webhooks as the user progresses through the flow.
KYC session records are stored in the prod-txn-plaid DynamoDB table.
KYC Session Statuses
kyc_status |
Description |
|---|---|
|
The session has been created and the user has not yet completed or abandoned it. |
|
Temporary status manually set only on the backend to signify a user has completed the KYC flow and we are waiting for a webhook from Plaid. |
|
The session requires manual review before a decision can be made. |
|
Identity verification passed. The user is cleared to proceed. |
|
Identity verification failed. A rejected loan application is created in the LOC Service. |
|
The session expired before the user completed it. |
|
The user or system canceled the session. |
Watchlist Status
The watchlist_status field tracks the result of Plaid’s watchlist (OFAC/sanctions) screening, which runs as part of the verification flow.
watchlist_status |
Description |
|---|---|
|
Watchlist screening is in progress. |
|
Watchlist result requires manual review. |
|
No matches found — user is cleared. |
|
A watchlist match was found. |
Verification Steps
A KYC session progresses through up to seven steps. Each step has a status (typically a string from Plaid such as not_started, active, passed, failed, skipped).
| Step | Description |
|---|---|
|
User accepts the Terms of Service for the identity verification session. |
|
User verifies their phone number via SMS code. |
|
Core identity check against authoritative data sources. |
|
User uploads a government-issued ID document. |
|
User takes a selfie that is compared against their uploaded document. |
|
User’s identity is checked against global sanctions and watchlists. |
|
Risk assessment based on the collected identity signals. |
Session Lifecycle
POST /{user_id}/transactions/kyc
{ first_name, last_name, email, address, city,
state, zip, phone_number, template_id, is_retry }
│
▼
Create Identity Verification session at Plaid
(or create a retry session if is_retry = true)
│
▼
Save KYC session record to DynamoDB
kyc_status: active
watchlist_status: processing
│
▼
Return 201 with KycSession object
In-App Verification
After a session is created, the mobile app launches the Plaid Link KYC flow. A link token is required to embed the flow in the app.
POST /{user_id}/transactions/kyc/link
│
▼
Look up most recent KYC session for user
│ No session found → 404
▼
Get KYC link token from Plaid
│
▼
Return 200 with { link_token, expires_at }
Completion Signal
When the user finishes all in-app steps, the mobile app calls the completion endpoint to signal the backend.
POST /{user_id}/transactions/kyc/completed
│
▼
Look up most recent KYC session for user
│ No session found → 404
▼
Update session status in DynamoDB → "processing"
│
▼
Return 200 with updated KycSession
Marking a session as "completed" on the client side only signals that the user finished the in-app steps. The final kyc_status (success, failed, etc.) is set asynchronously via the IDENTITY_VERIFICATION Plaid webhook.
|
Status Updates via Webhook
Plaid sends an IDENTITY_VERIFICATION / STATUS_UPDATED webhook when the session status changes. The miner Lambda processes it:
IDENTITY_VERIFICATION webhook received (STATUS_UPDATED)
│
▼
Fetch KYC session from Plaid API
│
▼
Create or update IdentityVerification record in DynamoDB:
kyc_status, watchlist_status, steps, timestamps
│
▼
Route by kyc_status:
├─ failed → Create rejected loan application in LOC Service
└─ success, active, expired, canceled, pending_review
└─► Logged (downstream actions to be implemented)
Watchlist status updates arrive via a separate SCREENING / STATUS_UPDATED webhook and update the watchlist_status field on the existing record.
Retrieving a Session
GET /{user_id}/transactions/kyc
│
▼
Return the most recent KYC session for the user
│ No session found → 404
API Reference
| Method | Path | Description |
|---|---|---|
|
|
Create a new KYC session, or a retry session. Returns the created |
|
|
Get the most recent KYC session for the user. |
|
|
Get a Plaid link token to launch the in-app KYC flow. |
|
|
Signal that the user has completed all in-app KYC steps. |
Error Reference
| HTTP Status | error_code |
Description |
|---|---|---|
|
|
Required fields missing or malformed in the request body. |
|
|
No KYC session exists for the user. |
|
|
An unexpected error occurred during session creation or retrieval. |
Related Pages
-
Plaid Mining Pipeline — How
IDENTITY_VERIFICATIONwebhooks are processed -
Features — KYC capability summary
-
API Specification — Full OpenAPI spec for KYC endpoints