Cardholders & Compliance
Every Cardholder moves through a compliance-driven lifecycle before any Card can be issued to them. This page covers the full status model, the two compliance paths (Didit-hosted KYC and SumSub), which fields become locked once review begins, and the documents collected as part of KYC.
Recall from Program Architecture:
A Cardholder is always a natural person, even when, internally at least, the Program serves a corporate client.
The status model
status | Name | Meaning |
|---|---|---|
0 | Pending | A transitional state between other statuses — generally brief, observed in passing during state changes rather than as a resting state |
1 | Approved | KYC passed — Cards can now be issued to this Cardholder |
2 | Compliance Decline | KYC failed programmatically |
3 | Under Review | Submitted for compliance review; awaiting outcome |
4 | Draft | Created but not yet submitted for compliance review |
5 | Deleted | Removed |
6 | Error | A processing error occurred during compliance review |
7 | Admin Decline | Manually declined |
Lifecycle
stateDiagram-v2
[*] --> (4)Draft: Create Cardholder POST /cardholders
(4)Draft --> (4)Draft: Edit Cardholder PUT /cardholder/{cardholderId}
(4)Draft --> (3)UnderReview: Submit to compliance POST /cardholders/{cardholderId}/kyc-submit
(4)Draft --> (5)Deleted: DELETE /cardholders/{cardholderId}
(3)UnderReview --> applicationLink
state fork_state <<fork>>
applicationLink --> fork_state: Cardholder submits KYC
fork_state --> (1)Approved: Application succeeds
fork_state --> NotApproved: Application fails
NotApproved --> fork_state: Manual review
state NotApproved {
[*] --> (2)ComplianceDecline: Automatically declined
[*] --> (7)AdminDecline: Manually declined
[*] --> (6)Error: Processing error
}
NotApproved --> (4)Draft: Edit Cardholder PUT /cardholder/{cardholderId}
NotApproved --> applicationLink: Refresh applicationLink POST /cardholders/{cardholderId}/ky-url/refresh
NotApproved --> (5)Deleted: DELETE /cardholders/{cardholderId}
(1)Approved --> [*]
(5)Deleted --> [*]
note right of (4)Draft
Status 0 (Pending) is a brief transitional state that may be observed during any of these transitions, rather than a resting state.
end note
classDef notStatus fill:white
class applicationLink notStatus
class Completed notStatus
class NotCompleted notStatus
class Expires notStatus
class if_state notStatus
Only Cardholders with status = 1 (Approved) can have Cards issued to them — see Cards: Virtual & Physical and Issue a Virtual Card.
The onboarding sequence
sequenceDiagram
participant You
participant Axys
participant Cardholder
You->>Axys: POST /cardholders
Axys->>You: cardholderId and Draft status
Note over You,Axys: Optional edit while in Draft
You->>Axys: PUT /cardholders/{cardholderId}/kyc-submit
Axys->>You: Under Review status
rect rgb(0,0,0,0.1)
Note over You,Cardholder: Cardholder compliance submission
Axys->>You: applicationLink for Didit KYC
You->>Cardholder: Share applicationLink
Cardholder->>Axys: Submit photo ID and proof of address
Cardholder->>Axys: Complete liveness check
end
Axys->>Axys: Compliance review
alt Approved
Axys->>You: Approved status
else Declined
Axys->>You: Declined status
alt Retry
You->>Axys: POST /cardholders/{cardholderId}/kyc-url/refresh
Note over You,Cardholder: Return to Cardholder compliance submission flow
else Edit
Note over You,Cardholder: Edit Cardholder before resubmitting to compliance
else Review
Note over You,Cardholder: Request manual compliance review
end
end
Two compliance paths
Didit (default)
By default (sumsubEnabled = 0), submitting a Cardholder for review (PUT /cardholders/{cardholderId}/kyc-submit) generates an applicationLink — a hosted URL where the Cardholder completes their KYC:
- Government-issued photo ID
- Proof of address
- Liveness verification
If the link expires or the Cardholder needs to retry, regenerate it with POST /cardholders/{cardholderId}/kyc-url/refresh. You can't regenerate a KYC URL when a Cardholder status = 1 (Approved), 4 (Draft) or 5 (Deleted), or 3 if there is already a valid KYC URL.
SumSub (token-based)
Setting sumsubEnabled = 1 (at creation via POST /cardholders, or via update before review begins) switches the Cardholder to a SumSub-based compliance flow, which requires a SumSub authentication token rather than the Didit applicationLink.
Enabling SumSub for a Program requires a specific onboarding and compliance framework. The SumSub flow's endpoints and token exchange sit alongside the
sumsubEnabledflag described here. If your Program is authorized for SumSub, you will be provided with the token-exchange process at the time of onboarding. Further assistance is available via the support channels.
KYC documents
As part of the compliance process, the platform tracks the documents submitted by the Cardholder:
| Field | Type | Description |
|---|---|---|
kycDocID | integer | Unique ID for this document record |
status | integer | Document-level review status |
docType | integer | Document type (e.g. passport, national ID, proof of address) |
lang | string | Document language |
number | string | Document number |
issueBy | string | Issuing authority |
issuerDate | string | Issue date |
expireDate | string | Expiry date |
image_FrontExt | string | File extension of the front-side image |
image_BackExt | string | File extension of the back-side image |
This array is returned as kycDocs on GET /cardholders/{cardholderId}.
The KYC documents and liveness test submitted through Didit are part of an automated biometric compliance flow and they are not returned in this array by default — the array will return empty. The platform assumes that the API User should not have access to retrieve and retain such personally identifiable information. Each Program should make its own arrangements for retaining their Cardholders' KYC documents, if they intend (and are authorized) to do so.
Field-lock rules
Once a Cardholder enters status = 3 (Under Review) or status = 1 (Approved), a large set of compliance-relevant fields become permanently locked — they cannot be changed via PUT /cardholders/{cardholderId}/update, even after returning to a non-approved state. Double-check these before submitting for review:
| 🔒 Locked once Under Review or Approved | ✏️ Always editable |
|---|---|
firstName | transactionLimit |
midName | callingCode |
lastName | countryCallingCode |
gender | phoneNum |
nationality | cellNum |
placeOfBirth | emailAdr |
dob | adrLine2 |
adrLine1 | cardHolderFirstName |
city | cardHolderLastName |
state | employeeID |
country | |
zipCode | |
sumsubEnabled |
Every locked field above is identity or KYC-document data — the information that must match the Cardholder's government-issued ID and proof of address. Get these right in your initial
POST /cardholderscall; there's no path to correct a typo in, say,doborcountryafter submission without creating a new Cardholder record.
Cardholder Account
On creation, the platform automatically provisions the Cardholder's internal Cardholder Account — see Accounts, Wallets & Deposit Addresses. This is not a separately addressable resource.
Bank account and deposit-address registration
Approved Cardholders can register an external bank account (for bank-rail funding, with OTP verification) as a sub-resource. Digital-asset Deposit Addresses, by contrast, are generated automatically per-Card at issuance and require no registration. Both are covered in full in Funding & Deposits.
What's next
Updated 22 days ago
