Identity verification
Three providers, one onboarding flow. The most common technical-buyer question is "who actually holds the KYC data?" — this page answers it.
The matrix
| Check | Provider | Triggered when | What they see |
|---|---|---|---|
| Business KYB | Banking partner | Workspace creation → submitKybAction() | Legal name, EIN, formation date, beneficial owners, control persons |
| KYC of beneficial owners | Banking partner (bundled) | Same form as KYB | Each owner: name, DOB, SSN last 4, address, ownership % |
| Cardholder verification (business cards) | Issuing partner | POST /api/cardholders | Accepts bank-verified control persons OR re-verifies via issuing partner KYC |
| Standalone consumer KYC | Persona | /onboarding/personal → createInquiry() | Government ID + selfie + liveness + watchlist check |
| OFAC / sanctions | Banking partner + Persona at onboarding; we re-screen nightly | Continuous | Match against OFAC SDN, EU consolidated, UN sanctions |
| Travel Rule (crypto >$3k) | Issuing partner | Per intl-payment / offramp >$3k | Originator + beneficiary info exchange per FATF Recommendation 16 |
Why three providers, not one
Our banking partner verifies businesses but requires a business entity — it can't verify a consumer who doesn't have one.
Our issuing partner verifies cardholders but expects either bank-style business context OR an external KYC token (we use Persona's).
Persona verifies individuals standalone — ID + selfie + liveness — which is the only path that fits Phase D (consumer self-custody card with no business attached).
Soren Pay's role
We orchestrate. We never store:
- Raw government IDs (Persona holds these)
- SSNs / DOBs of beneficial owners (our banking partner holds these in their KYB tool)
- Card PANs (our issuing partner's PCI-scope iframe)
We do store:
- The provider case ID (
kyb_records.provider_case_id,kyc_records.provider_inquiry_id) - The decision outcome (
kyb_status,personal_accounts.status) - The hashed reference to fetch from the provider's tool
Data retention
| Data | Storage | Retention | |---|---|---| | KYB documents | Banking partner's tool | 5 yr after account closure (banking partner policy) | | KYC documents | Persona's tool | 5 yr (Persona policy) | | KYB decision + provider_case_id | Soren Pay Postgres | 7 yr (BSA) | | Ledger entries | Soren Pay Postgres | 7 yr (BSA) | | Auth logs | Soren Pay Postgres | 2 yr (operational) | | Card PANs | Never stored | N/A |
Subject access requests / data deletion
GDPR / CCPA: email privacy@sorenpay.com with the user's email or workspace id. We'll fetch from each provider on request.
Note: regulatory records (ledger, KYB decisions) cannot be deleted within the retention window per BSA. We can delete UI-layer cached PII but not the regulated records.
OFAC re-screening
Background cron (nightly): we re-screen every active workspace + personal account against the latest OFAC SDN diff. Hits → workspace/account freezes
- alert to compliance@sorenpay.com.
Travel Rule
For crypto transfers > $3,000 USD equivalent (off-ramp or international payment), our issuing partner exchanges originator + beneficiary information per FATF guidance. Transparent to your API call — you don't pass anything extra.
Audit trail
Every state transition (KYB pending → approved, KYC submitted → declined,
OFAC hit → frozen) is logged in auth_audit_chain with a SHA-256 hash
chained to the previous entry. Tampering breaks the chain.
Related
- Compliance overview
- Card capabilities — our issuing partner's PCI-DSS
- Disputes + chargebacks — Visa's role