Document Type: Onboarding Flow Specification
Date: December 29, 2025
Status: READY FOR IMPLEMENTATION
Target: EU (MiCA) compliant, staff-assisted venue onboarding
Context: In-venue, staff-assisted onboarding where users create wallets with guidance. No drop-off concerns.
Regulatory: EU (MiCA) requires KYC before ANY transactions → KYC-first flow mandatory.
Goal: <5 minute onboarding, 90%+ KYC success rate, immediate wallet activation.
Key Innovation: Staff-guided parallel onboarding via QR code sessions + Sumsub instant verification.
┌─────────────────────────────────────────────────────────┐
│ VENUE-ASSISTED KYC-FIRST ONBOARDING │
│ Staff member guides user, <5 minutes total │
├─────────────────────────────────────────────────────────┤
│ │
│ MINUTE 0-1: Staff Initiates Session │
│ ├─ Staff opens onboarding portal (tablet/kiosk) │
│ ├─ Generates unique session QR code │
│ ├─ User scans with their phone │
│ └─ Redirects to OAuth login │
│ │
│ MINUTE 1-2: User Login (on their phone) │
│ ├─ User clicks "Sign in with Apple" or "Google" │
│ ├─ OAuth popup (Face ID/fingerprint) │
│ ├─ Server creates user account │
│ └─ Redirects to KYC immediately │
│ │
│ MINUTE 2-4: KYC Verification (Sumsub) │
│ ├─ Sumsub widget opens (on user's phone) │
│ ├─ Staff guides user: │
│ │ ├─ "Hold ID flat, good lighting" │
│ │ ├─ "Take selfie - remove sunglasses" │
│ │ └─ "Proof of address - utility bill or bank" │
│ ├─ Documents uploaded │
│ └─ Sumsub processes (instant or ~2 min wait) │
│ │
│ MINUTE 4: KYC Approved ✓ │
│ ├─ User's phone shows: "Verified!" │
│ ├─ Staff tablet shows: ✓ [User Name] Approved │
│ └─ Immediately unlock wallet creation │
│ │
│ MINUTE 4-5: Wallet Creation (instant) │
│ ├─ User clicks "Create Wallet" │
│ ├─ 12-word seed phrase generated │
│ ├─ Screen shows: "Write these 12 words" │
│ ├─ Staff hands user paper backup card │
│ ├─ User writes words (or takes photo temporarily) │
│ ├─ User sets encryption password (PIN/biometric) │
│ ├─ Seed encrypted in IndexedDB │
│ └─ Wallet address generated │
│ │
│ MINUTE 5: Onboarding Complete │
│ ├─ Staff: "You're all set! Here's your QR code" │
│ ├─ User receives: │
│ │ ├─ Paper wallet backup card (with 12 words) │
│ │ ├─ QR code sticker (wallet address for receiving) │
│ │ └─ Quick start guide │
│ ├─ Dashboard shows: TRX, USDT, USDC balances (zero) │
│ └─ Staff demos: "Receive funds by showing QR" │
│ │
│ POST-VENUE: User leaves with: │
│ ├─ ✓ Verified account (KYC approved) │
│ ├─ ✓ Active wallet (can send/receive immediately) │
│ ├─ ✓ Paper backup (seed phrase secured) │
│ └─ ✓ Login remembered (OAuth session on their phone) │
│ │
└─────────────────────────────────────────────────────────┘
| Decision | Reason |
|---|---|
| KYC before wallet | MiCA compliance - no transactions before verification |
| QR code sessions | Parallel onboarding - staff handles 3-5 users simultaneously |
| User's phone | Privacy + ownership (seed never on staff device) |
| Paper backups | Physical security + user trust (handed at venue) |
| OAuth login | No password fatigue, biometric auth |
| Sumsub instant | <60s verification for 80% of users |
┌─────────────────────────────────────────────────────────┐
│ STAFF TABLET VIEW │
├─────────────────────────────────────────────────────────┤
│ │
│ [Start New Onboarding] │
│ │
│ Active Sessions: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ #2847 - John D. ⏱️ 2:34 │ │
│ │ Status: ⏳ KYC Processing... │ │
│ │ [View Progress] [Cancel] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ #2846 - Sarah M. ⏱️ 4:12 │ │
│ │ Status: ✓ Complete - Wallet created │ │
│ │ [Print Backup] [Email Guide] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Today's Stats: │
│ ├─ Onboarded: 142 users │
│ ├─ Avg time: 4m 23s │
│ ├─ KYC success rate: 94% │
│ └─ Failed verifications: 8 (6 retried successfully) │
│ │
│ Alerts: │
│ ⚠️ Sumsub API slow (avg 3m response time) │
│ │
└─────────────────────────────────────────────────────────┘
Staff Actions:
[Start New Onboarding]→ Generates QR code, creates session[View Progress]→ Shows detailed step-by-step status[Cancel]→ Expires session if user abandons[Print Backup]→ Prints seed phrase card (if printer available)[Email Guide]→ Sends quick start guide to user's email
Session Lifecycle:
Created → User Scanned → OAuth Complete → KYC Uploaded
→ KYC Processing → KYC Approved → Wallet Created → Complete
Timeout: 10 minutes (auto-expire if no activity)
Staff can handle 3-5 users simultaneously:
Timeline (Single Staff Member):
10:00 - User A: Start session, hand phone to user
10:01 - User B: Start session, hand phone to user
10:02 - User C: Start session, hand phone to user
10:03 - User A: KYC approved ✓ → Help with wallet creation
10:04 - User B: KYC approved ✓ → Help with wallet creation
10:04 - User D: Start new session (User A done)
10:05 - User C: KYC approved ✓ → Help with wallet creation
10:05 - User A: Leaves with backup card
Average throughput: 10-15 users/hour per staff member
Sumsub Settings:
├─ Mode: "Assisted verification"
├─ Auto-approve: Low-risk countries (EU residents)
├─ Instant check: ID validation + liveness detection
├─ Skip: Proof of address if ID shows address
├─ Fallback: Manual review queue (5 min SLA)
└─ Priority: Tag venue sessions as "high priority"
Expected turnaround:
├─ 80% of users: <60 seconds
├─ 15% of users: 2-3 minutes
└─ 5% of users: Manual review (5-10 minutes)
Pre-printed materials at venue:
├─ Seed phrase backup cards (write 12 words)
│ ├─ High-quality cardstock
│ ├─ Tamper-evident design
│ └─ Security tips printed on back
│
├─ QR code stickers (wallet address)
│ ├─ Generated on-demand (staff printer)
│ └─ User can stick on phone case
│
├─ Quick start guides (fold-out card)
│ ├─ How to receive crypto
│ ├─ How to send crypto
│ ├─ Security best practices
│ └─ Support contact info
│
└─ Branded swag (optional)
├─ Builds trust
└─ Marketing material
IF KYC fails:
├─ Staff immediately sees alert on tablet
├─ Common issues + fixes:
│ │
│ ├─ Blurry photo
│ │ └─ Staff helps retake: "Hold phone steady, good lighting"
│ │
│ ├─ Expired ID
│ │ └─ Use alternative: passport, driver license, national ID
│ │
│ ├─ Name mismatch
│ │ └─ Check: middle name, nicknames, married name
│ │
│ ├─ Glare on ID
│ │ └─ Remove from plastic sleeve, tilt to avoid reflection
│ │
│ ├─ Under 18
│ │ └─ Apologize, can't onboard (regulatory requirement)
│ │
│ └─ Wrong document type
│ └─ Guide to acceptable docs (show examples)
│
└─ Retry flow keeps same session (no re-login needed)
// Staff initiates session
POST /api/venue/session/start
{
venue_id: "venue-123",
staff_id: "staff-456"
}
Returns: {
session_id: "sess_abc123",
qr_code_url: "https://wallet.example.com/onboard?s=sess_abc123",
qr_code_svg: "<svg>...</svg>", // For display on tablet
expires_in: 600 // 10 minutes
}
// User scans QR, sees:
GET /onboard?s=sess_abc123
→ Validates session (not expired, not used)
→ Redirects to OAuth with session context
→ After OAuth, links user_id to session_id
→ Redirects to KYC
// Staff dashboard polls for status
GET /api/venue/session/sess_abc123/status
Returns: {
session_id: "sess_abc123",
user: {
name: "John Doe",
email: "[email protected]"
},
steps: [
{
step: "oauth",
status: "completed",
timestamp: "2025-12-29T10:00:00Z"
},
{
step: "kyc_upload",
status: "completed",
timestamp: "2025-12-29T10:02:00Z"
},
{
step: "kyc_verification",
status: "in_progress",
timestamp: "2025-12-29T10:03:00Z",
details: "Processing documents..."
},
{
step: "wallet_creation",
status: "pending"
}
],
elapsed_time: 187, // seconds
current_step: "kyc_verification"
}
// Cancel session
POST /api/venue/session/sess_abc123/cancel
{
reason: "user_abandoned" | "staff_cancelled"
}// Option A: Server-Sent Events (SSE)
GET /api/venue/session/sess_abc123/stream
Staff tablet opens SSE connection, receives:
event: step_completed
data: {"step": "oauth", "status": "completed"}
event: step_started
data: {"step": "kyc_verification", "status": "in_progress"}
event: kyc_approved
data: {"user": "John Doe", "timestamp": "2025-12-29T10:04:00Z"}
// Option B: WebSocket (if SSE not supported)
WS /api/venue/session/sess_abc123/ws
// Option C: Short polling (fallback)
Poll GET /api/venue/session/sess_abc123/status every 2 seconds// Server creates Sumsub session when user starts KYC
POST /api/kyc/init
{
session_id: "sess_abc123",
user_id: "user_xyz"
}
Server calls Sumsub API:
POST https://api.sumsub.com/resources/applicants
{
externalUserId: "user_xyz",
levelName: "basic-kyc-level",
metadata: {
venue_session: "sess_abc123",
onboarding_type: "venue_assisted"
}
}
Returns: {
applicant_id: "app_123",
access_token: "token_abc" // For user's phone
}
// User's phone loads Sumsub widget
<iframe src="https://api.sumsub.com/idensic/...?token=token_abc"></iframe>
// Sumsub sends webhook on completion
POST /webhook/kyc
{
applicantId: "app_123",
externalUserId: "user_xyz",
reviewStatus: "completed",
reviewResult: {
reviewAnswer: "GREEN" | "RED" | "YELLOW"
}
}
Server:
├─ Updates user.kyc_status = 'approved'
├─ Triggers SSE to staff dashboard: ✓ KYC Approved
├─ Triggers push to user's phone: "Verified! Create wallet"
└─ Unlocks wallet creation button
// If RED (rejected):
├─ Parse reviewResult.rejectLabels (expired_document, poor_quality, etc.)
├─ Show user-friendly message: "ID expired - please use valid document"
└─ Allow retry (1-2 attempts before manual review)-- TABLE: venue_sessions
CREATE TABLE venue_sessions (
id TEXT PRIMARY KEY,
session_id TEXT UNIQUE NOT NULL,
venue_id TEXT NOT NULL,
staff_id TEXT NOT NULL,
user_id TEXT, -- NULL until OAuth complete
qr_code_url TEXT NOT NULL,
status TEXT DEFAULT 'created', -- 'created' | 'active' | 'completed' | 'cancelled' | 'expired'
steps_completed TEXT, -- JSON: ["oauth", "kyc_upload", ...]
current_step TEXT, -- "oauth" | "kyc_verification" | "wallet_creation"
created_at DATETIME DEFAULT NOW(),
expires_at DATETIME NOT NULL, -- created_at + 10 minutes
completed_at DATETIME,
INDEX (venue_id),
INDEX (staff_id),
INDEX (status),
INDEX (created_at)
);
-- TABLE: venues (venue metadata)
CREATE TABLE venues (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
location TEXT,
active INTEGER DEFAULT 1,
created_at DATETIME DEFAULT NOW(),
INDEX (active)
);
-- TABLE: staff (staff accounts)
CREATE TABLE staff (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
venue_id TEXT NOT NULL,
role TEXT DEFAULT 'onboarding', -- 'onboarding' | 'manager' | 'admin'
active INTEGER DEFAULT 1,
created_at DATETIME DEFAULT NOW(),
FOREIGN KEY (venue_id) REFERENCES venues(id),
INDEX (venue_id),
INDEX (active)
);Staff Station:
├─ iPad/Android tablet (10"+ screen)
│ ├─ Running staff dashboard web app
│ ├─ Mounted on stand (hands-free operation)
│ └─ Charging cable (all-day operation)
│
├─ WiFi connection (backup: cellular hotspot)
│ ├─ Primary: Venue WiFi
│ ├─ Backup: Staff's phone hotspot
│ └─ Failover: Automatic switch
│
├─ Printer (optional)
│ ├─ Thermal printer for QR stickers
│ ├─ Connected via Bluetooth
│ └─ Battery-powered (portable)
│
└─ Physical materials
├─ Seed phrase backup cards (stack of 100)
├─ Pens (3-5 backup pens)
├─ Quick start guides (stack of 100)
└─ Branded materials
User Requirements:
├─ Smartphone (iOS 14+ / Android 10+)
├─ Camera (for ID photos)
├─ Internet connection (venue WiFi or cellular)
└─ Apple/Google account (for OAuth)
IF internet drops:
├─ Staff dashboard shows: "⚠️ Offline - operations queued"
├─ Queue operations locally (IndexedDB on tablet)
│ ├─ Store session metadata
│ ├─ Queue status updates
│ └─ Sync when connection restored
│
├─ User flow impact:
│ ├─ OAuth: FAILS (requires internet)
│ ├─ Sumsub KYC: FAILS (requires internet)
│ ├─ Wallet creation: WORKS (offline seed generation)
│ └─ Server sync: QUEUED (will sync when online)
│
└─ Recovery:
├─ Auto-detect connection restored
├─ Sync queued operations
└─ Notify staff: "✓ Back online - syncing..."
CRITICAL DEPENDENCY: Sumsub KYC requires internet (can't be queued)
Staff should have backup cellular hotspot if venue WiFi unreliable.
Staff Training - Privacy Best Practices:
1. Tablet positioning
├─ Angle away from crowds
├─ Use privacy screen protector (viewing angle <45°)
└─ Don't leave unattended
2. User data handling
├─ Never ask user to show ID to staff
├─ Never photograph user's ID with staff device
├─ All uploads happen on user's phone
└─ Staff only sees: name, email, status
3. Seed phrase security
├─ Remind user: "Keep these 12 words private"
├─ Don't read seed phrase aloud
├─ Shield user's screen when writing words
└─ Shred failed/duplicate backup cards immediately
4. GDPR compliance
├─ Session data auto-deleted after 24 hours
├─ Staff dashboard doesn't cache PII
├─ User can request data deletion anytime
└─ Venue sessions logged for audit trail (30 days)
Admin Dashboard (venue-wide view):
GET /api/admin/venues
Returns all venues with real-time stats:
[
{
venue_id: "venue-123",
name: "Berlin Trade Show",
location: "Berlin, Germany",
active_sessions: 5,
completed_today: 142,
avg_onboarding_time: "4m 23s",
kyc_success_rate: 0.94,
staff: [
{ staff_id: "staff-456", name: "Anna", active_sessions: 2 },
{ staff_id: "staff-789", name: "Max", active_sessions: 3 }
]
},
{
venue_id: "venue-456",
name: "Amsterdam Conference",
location: "Amsterdam, Netherlands",
active_sessions: 8,
completed_today: 203,
avg_onboarding_time: "3m 57s",
kyc_success_rate: 0.91,
staff: [...]
}
]
Admin can:
├─ View all venues + staff in real-time
├─ See aggregate stats across venues
├─ Pause/resume venue onboarding (maintenance mode)
├─ Add/remove staff members
└─ Download reports (CSV export)
Target KPIs (per venue, per day):
Onboarding Speed:
├─ P50 (median): <4 minutes
├─ P80: <5 minutes
├─ P95: <7 minutes
└─ Target: 80% complete in <5 minutes
KYC Success Rate:
├─ First attempt: >85%
├─ After 1 retry: >95%
├─ Manual review needed: <5%
└─ Target: >90% first attempt
Staff Throughput:
├─ Per staff member: 10-15 users/hour
├─ During peak hours: 12+ users/hour
├─ During off-peak: 8+ users/hour
└─ Target: 12 users/hour average
User Satisfaction:
├─ In-venue survey (optional): >4.5/5 stars
├─ Post-venue activation: >60% use wallet within 7 days
├─ Repeat usage: >40% active after 30 days
└─ Support requests: <2% of onboarded users
System Reliability:
├─ API uptime: 99.9%+
├─ Sumsub API latency: <3 seconds P95
├─ Session creation time: <500ms
└─ Zero data loss incidents
Admin View - Live Metrics:
┌─────────────────────────────────────────────────────────┐
│ LIVE ONBOARDING METRICS │
├─────────────────────────────────────────────────────────┤
│ │
│ Active Venues: 3 │
│ Active Sessions: 12 │
│ │
│ Today (All Venues): │
│ ├─ Completed: 487 users │
│ ├─ In Progress: 12 users │
│ ├─ Failed/Cancelled: 23 users │
│ └─ Avg Time: 4m 18s │
│ │
│ KYC Performance: │
│ ├─ Success Rate: 92% │
│ ├─ Avg Verification Time: 1m 34s │
│ └─ Manual Reviews: 8 (waiting: 3, approved: 5) │
│ │
│ Alerts: │
│ ⚠️ Venue "Amsterdam Conference" - Sumsub slow (4m avg) │
│ ℹ️ Venue "Berlin Trade Show" - High volume (20 active)│
│ │
└─────────────────────────────────────────────────────────┘
-
Venue Type
- Trade show booth?
- Retail store?
- Event entrance/registration?
- Mobile popup (food truck style)?
Impact: Hardware requirements, space constraints, power availability
-
Sumsub Tier
- Current plan: Instant verification OR async review?
- Average turnaround time?
- Manual review SLA?
Impact: User wait time, staff throughput
-
Staff Training
- Technical skill level?
- Previous crypto experience?
- Languages spoken (multilingual support)?
Impact: Dashboard complexity, error recovery flows
-
Volume Expectations
- Users per day? (10s, 100s, 1000s?)
- Peak hours vs off-peak?
- Multi-day events or ongoing operation?
Impact: Infrastructure scaling, staff scheduling
-
Post-Venue Engagement
- Email campaigns?
- Push notifications?
- Follow-up activation incentives?
Impact: Retention strategy, long-term activation
-
Multi-Language Support
- Primary languages: English, German, Dutch?
- Sumsub supports 200+ languages
- Staff dashboard translations needed?
Impact: Localization effort
-
Seed Phrase Backup Strategy
- Paper only? (handed at venue)
- Optional digital backup? (encrypted cloud)
- Recovery mechanism if user loses paper?
Impact: User support burden
-
Offline Mode Requirements
- How critical is offline functionality?
- Backup cellular hotspot available?
- Queue operations vs fail-fast?
Impact: Network resilience design
PHASE 1: Core Onboarding (Week 1-2)
├─ Build staff dashboard (session management)
├─ Implement QR code session flow
├─ Integrate Sumsub KYC (basic)
├─ Build wallet creation UI (post-KYC)
└─ Test end-to-end with test users
PHASE 2: Venue Deployment (Week 3)
├─ Hardware procurement (tablets, printer)
├─ Physical materials design (backup cards, guides)
├─ Staff training materials
├─ Pilot test at single venue (1 day)
└─ Iterate based on feedback
PHASE 3: Multi-Venue Rollout (Week 4)
├─ Admin dashboard (multi-venue management)
├─ Real-time monitoring + alerts
├─ Network resilience (offline mode)
├─ Deploy to 2-3 venues
└─ Monitor metrics, optimize flows
PHASE 4: Scale & Optimize (Week 5+)
├─ Performance tuning (reduce onboarding time)
├─ Staff feedback integration
├─ Post-venue engagement campaigns
└─ Scale to 10+ venues
TECHNICAL:
☐ Sumsub account + instant verification enabled
☐ Cloudflare Workers + D1 deployed
☐ Staff dashboard tested on iOS + Android tablets
☐ QR code generation working
☐ OAuth (Apple + Google) configured
☐ Wallet creation flow tested (100+ test seeds)
☐ Network failover tested (WiFi → cellular)
☐ Session timeout + cleanup tested
OPERATIONAL:
☐ Hardware ordered (tablets, printers, stands)
☐ Physical materials printed (backup cards, guides)
☐ Staff accounts created + credentials shared
☐ Staff training session scheduled (1-2 hours)
☐ Venue WiFi tested (bandwidth, reliability)
☐ Backup cellular hotspot configured
☐ Support escalation process defined
LEGAL/COMPLIANCE:
☐ MiCA compliance reviewed by legal counsel
☐ GDPR data handling documented
☐ Privacy policy updated (venue onboarding)
☐ User consent flows reviewed
☐ Sumsub DPA (Data Processing Agreement) signed
MONITORING:
☐ Admin dashboard deployed
☐ Real-time metrics working
☐ Alerting configured (Slack/email)
☐ Error tracking (Sentry) enabled
☐ Backup/restore procedures tested
This onboarding flow optimizes for:
- ✅ Compliance: MiCA-compliant KYC-first approach
- ✅ Speed: <5 minute target with 90%+ success rate
- ✅ Throughput: 10-15 users/hour per staff member
- ✅ Privacy: User controls seed, staff never sees
- ✅ Resilience: Offline-capable where possible
- ✅ Scalability: Multi-venue support from day 1
Critical success factors:
- Sumsub instant verification (<60s for 80% of users)
- Staff training (error recovery, privacy best practices)
- Network reliability (WiFi + cellular backup)
- Physical materials quality (backup cards, guides)
- Real-time monitoring (catch issues early)
Let's build it. 🚀