Browse help guides
KYC
KYC data reference
For implementers and auditors: files, event types and payload keys, the Sumsub calls, the status mapping and the failure table.
Where it lives
| Path | Contains | Edit by hand? |
|---|---|---|
| subjects/SUB-….md | The user; kycStatus, currentApplicantId, kycOverridden, verifiedAt are copies written by the app. | Body only, never the KYC keys |
| kyc/events.jsonl | Applicant and provider events, append-only, hash-chained. | Never |
| config/kyc.yaml | Default method and the Sumsub connection (no secrets). | No — use Settings |
| audit/events.jsonl | One PII-free line per KYC event. | Never |
| OS keychain (userData/secrets.bin) | Encrypted Sumsub token and secret, outside the vault. | No |
Event types
| Type | When |
|---|---|
| provider.connected | Sumsub keys tested and saved. |
| provider.tested | Test pressed in Settings. |
| provider.disabled | Disconnect. |
| provider.fetch_requested | Fetch status pressed. |
| applicant.created | A KYC record starts (Sumsub or manual). |
| applicant.link_issued | A hosted Sumsub link is minted. |
| applicant.fetched | Sumsub's current answer, recorded on every fetch. |
| applicant.status_changed | The status actually changed (fetch, webhook or manual). |
| applicant.manual_override | Compliance or owner override. |
seq 1, 2, 3 …
id KEV-<ulid>
type one of the event types
at ISO-8601 with offset
actor who wrote it (the app)
actorRole owner | compliance | operator
subjectId SUB-<ulid> or null
applicantId APL-<ulid> or null
payload keys below
prevHash sha256 of the previous line
hash sha256 of this line without hashPayload keys
applicant.created
provider manual
provider_connection_id null
provider_ref "manual:{applicant_id}"
flow manual
level_name "manual"
applicant.status_changed
source manual
kyc_status pending | need_docs | approved | rejected
aml_status clear | hit | review | unknown
doc_type, doc_country, doc_valid_until, name_on_doc, dob_on_docapplicant.created
provider sumsub
provider_connection_id <active connection>
provider_ref <Sumsub applicantId>
flow link
level_name <connection level name>
applicant.link_issued
link_url
link_expires_at
token_ttl_sec 1800applicant.manual_override
from_kyc_status
to_kyc_status approved
reason_code staff_review | cba_instruction | data_fix | other
reason_text required
provider.connected
provider sumsub
mode byok
scopes applicant_create, applicant_read
secret_ref pointer only, never the key
environment, level_nameSumsub calls
POST /resources/applicants?levelName=
POST /resources/sdkIntegrations/levels/-/websdkLink
GET /resources/applicants/{id}/one
GET /resources/applicants/-;externalUserId={id}/oneEach request is signed: HMAC-SHA256 over timestamp + method + path with query + body, hex, sent as X-App-Access-Sig with X-App-Token and X-App-Access-Ts. The user's id (SUB-…) is the externalUserId. Not in this version: document upload, re-check requests, share tokens, level creation, or an embedded WebSDK.
Status mapping
| Sumsub review | KYC status |
|---|---|
| init | Not started (Link sent while a link is out) |
| pending / queued / onHold | Pending |
| completed + GREEN | Approved |
| completed + RED + RETRY | Needs documents |
| completed + RED + FINAL | Rejected |
Only the adapter reads GREEN or RED. Everything else — the badge, the booking gate, exports — reads the normalized KYC status.
The round trip
sequenceDiagram
actor Staff
participant Desk
participant Sumsub
actor Client
Staff->>Desk: Create user
Desk->>Sumsub: applicants + websdkLink
Desk-->>Staff: link
Staff->>Client: send link
Client->>Sumsub: documents + liveness
Sumsub-->>Desk: webhook or Fetch
Desk-->>Staff: badge approvedRules that always hold
- The access token used to mint a link is never stored; the link and its expiry are.
- Document details stay on the KYC record, not in the audit log.
- AI proposals cannot change KYC; only the app writes KYC events.
- The booking gate reads the user's KYC status; an override is visible as “approved (overridden)”.
- Vaults made before this feature are upgraded once on open (format 2), with a backup in .bak/. Posted transactions are never rewritten.
Something missing or out of date? Send feedback.
