Skip to main content

KYC tracking

UCRM supports four KYC ownership models — pick once per tenant, override per-player when needed.

Models

kyc_modelWho initiatesWho decidesWebhooks accepted
platform_ownsCasino platformPlatformYes — kyc.* lifecycle webhooks update CRM state
crm_ownsCRM admin (POST /v1/players/:id/kyc/request)CRM admin (POST .../approve)No — UCRM rejects inbound kyc.* webhooks (403)
dualEither sideEither side (split by KYC level — basic via platform, source-of-funds via CRM)Yes
noneNobody (test envs only)No

State machine

none → pending → verified
→ rejected
verified → expired (TTL refresh)
verified → pending (level upgrade)
rejected → pending (resubmit)
expired → pending (re-verify)

Forward-only. No verified → rejected (admin uses POST .../revoke which transitions to expired).

Levels

Operator-defined integer 0..10:

  • 0 — no KYC
  • 1 — basic ID (passport / driver's license)
  • 2 — address verification (utility bill)
  • 3 — source of funds
  • 4+ — operator-specific (enhanced due diligence, etc.)

Storage

players.kyc_status, players.kyc_level, players.kyc_history (append-only JSONB), players.kyc_last_event_at, players.kyc_expires_at (TTL for verified KYC).

Admin actions

POST /v1/players/:id/kyc/request — only available when tenant.kyc_model in {crm_owns, dual} AND adapter supports kyc.initiate. Transitions none → pending.

POST /v1/players/:id/kyc/approve — only available when tenant.kyc_model in {crm_owns, dual} AND adapter supports kyc.update. Transitions pending → verified. Optional expires_at for TTL.

POST /v1/players/:id/kyc/revoke — always available (admin override). Transitions current → expired.

Webhook events

Eventfrom → to
kyc.submittednone/rejected/expired → pending
kyc.approvedpending → verified
kyc.rejectedpending → rejected
kyc.expiredverified → expired
kyc.level_upgradedverified → pending (new higher level submission)

History entry shape:

{
"ts": "2026-05-08T12:00:00Z",
"from": "pending",
"to": "verified",
"level": 1,
"actor_kind": "platform" | "crm" | "admin",
"actor_id": "user_abc",
"reason": "documents accepted",
"data": { "provider_ref": "..." }
}

Capability mismatch

If your tenant picks crm_owns but the adapter doesn't support kyc.update, the admin UI displays a warning + disables the Approve button. Operators see the trade-off + can either change the adapter or switch to platform_owns.