Card Management (xperise card) — Functional Spec
A self-contained functional spec for card management in the Corporate Portal, detailed enough to drive flow and UI design. It builds on the two-layer model and the card lifecycle. Endpoint shapes are illustrative.
0. Scope & confirmed decisions
Card management is everything a corporate admin does to xperise cards: order/issue → inventory → assign → activate → fund & control → lifecycle actions → view/audit. Setting a card's card balance sets Layer 1 (spending authority); the company wallet is Layer 2 (funding). Card management never moves real money except by reclaiming balance to the wallet.
Confirmed product decisions that shape the flows:
| # | Decision |
|---|---|
| 1 | Max cards per employee is a hard cap — company-configured, enforced at assignment. |
| 2 | On reassign / replace, remaining balance is reclaimed to the company wallet by default (carry-over is an explicit opt-in). |
| 3 | A card can be issued in physical and/or virtual (in-app) form — it can be both at once. |
| 4 | Card balance reset is configurable: reset on a day of the month, or no reset. When there is no reset, the manager tops up when it runs empty. Top-up is always available regardless of the reset setting. |
| 5 | A company runs one operating model — monthly limit or cost center, never both. A card payment draws the card balance (plus the cost center only under the cost-center model) — it never draws the monthly limit. Under the monthly-limit model, the monthly limit governs non-card methods (wallet / QR), and a cardholder can hold both a monthly limit (for wallet/QR) and a card (spending its card balance). |
| 6 | Transaction authentication is the Cardholder Verification Method (CVM) — a PIN or an OTP, one of the two, never both — configured per card/company. |
| 7 | The card's funding source (Layer 2) is optional: the company wallet, or none — in which case the card balance is stored value (prepaid) and is itself the money. |
| 8 | A card is assigned to one employee or to no-one. Assigned to an employee, it inherits all the employee's cost center(s) and stays in sync — if the employee is removed from a cost center, the card is removed from it too. Unassigned = a bearer card: anyone holding it who knows the PIN can use it, and it may optionally be linked to one cost center. |
1. Card data model (fields for UI)
| Field | Type | Notes |
|---|---|---|
cardId | id | Internal id |
cardToken / last4 | string | Token is vaulted; UI shows •••• 1234 |
form | set | physical and/or virtual — a card can be both (virtual lives in the app) |
status | enum | see §2 |
holderEmployeeId | id? | null = bearer card (usable by whoever holds it + knows the PIN); set = assigned to that employee |
costCenters | list? | Assigned card: inherited from the employee — all their cost centers, kept in sync; the employee's default cost center is used for card payments (picker hidden). Bearer card: optional, at most one cost center, set via the picker |
cardBalance | money | Layer-1 bucket for this card (stored value when unfunded — §7) |
balanceReset | object | { mode: "day_of_month" | "none", dayOfMonth? } — reset config (§3.8) |
limits | object | perTransaction, daily, monthly |
allowedVendors / categories | list? | optional allow-list |
channelRules | object | tap / printed-QR / manual enabled? + CVM thresholds |
timeWindows | object? | business hours / days |
fundingSource | enum | optional: company_wallet | none (none ⇒ card balance is stored value) |
cvm | enum | Cardholder Verification Method: pin | otp (one of two, never both) |
expiryDate | date | |
pinStatus | enum? | not_set | set (only when cvm = pin; admin never sees the PIN) |
activationMethod | enum | employee_claim | admin_full |
batchId / orderRef | id? | for physical orders |
| timestamps | date | created / assigned / activated / lastUsed |
2. Card lifecycle (states & transitions)
| Status | Can spend? | Meaning |
|---|---|---|
ISSUED | No | Produced/created, in the company pool, unassigned |
ASSIGNED | No | Bound to an employee, awaiting activation |
ACTIVE | Yes | Spendable — assigned to an employee or unassigned (bearer) |
FROZEN | No | Temporarily blocked, reversible |
LOST | No | Reported lost/stolen — terminal, token killed |
CANCELLED | No | Terminated — terminal; balance reclaimed to wallet |
EXPIRED | No | Past expiry — terminal |
A card can move money only in ACTIVE. A bearer card goes straight ISSUED → ACTIVE
(no ASSIGNED step). Every transition is audit-logged with actor + reason.
3. Functions
Each function lists who (role), inputs, steps, rules, and edge cases.
3.1 Order physical cards (bulk)
- Who: card manager, super admin.
- Inputs: quantity, personalization (blank vs pre-printed name), shipping address(es), optional pre-assignment CSV, delivery contact.
- Steps: choose quantity/options → (optional) approval → submit → cards created
ISSUEDunder abatchId→ track fulfillment (Requested → Producing → Shipped → Delivered). - Rules: large orders may require approval; quantity caps per company policy.
- Edge cases: partial delivery; damaged-in-transit reorder; cancel batch before production.
3.2 Issue virtual card (instant, in app)
- Who: card manager, super admin.
- Inputs: employee (optional — omit for a bearer card), card balance +
balanceResetconfig, CVM (PIN/OTP; bearer ⇒ PIN), funding source (wallet/none), limits, cost center, optional expiry. - Steps: select employee → set policy → create →
ACTIVE(orASSIGNEDif employee-claim required) → credentials revealed only in the employee app (never emailed in clear). - Edge cases: employee has no account → invite first; enforce the per-employee hard cap (§3.5).
3.3 Card inventory (list view)
- Who: all admin roles (auditor read-only).
- Features: columns (last4, holder, dept/cost center, status, balance, last used); filter by status/type/department/cost center/holder/balance; search by last4/holder/order; bulk-select; status chips; export CSV; pagination.
- Bulk actions: assign, freeze, adjust limits, cancel (§3.13).
3.4 Card detail view
- Who: all admin roles.
- Shows: all fields (§1); balance allocated vs remaining + next reset date; limits & controls; holder + cost center; activation status; this card's transaction history; audit trail.
- Actions (state-dependent): assign/reassign, activate/resend claim, adjust balance, edit limits, freeze/unfreeze, replace, report lost, cancel.
3.5 Assign card — to an employee, or leave as a bearer card (single + bulk)
At the assignment step you choose one of two targets:
- One employee — the card is bound to that person; it inherits the employee's default cost center, enforces the hard cap (max cards/employee), and may use PIN or OTP as its CVM.
- No-one (a bearer card) — the card has no holder and is usable by whoever holds it and knows the PIN; its CVM is therefore PIN only, and it may optionally be linked to one cost center on the card itself.
Never more than one employee. The same choice can be changed later via reassign / unassign.
A card is assigned to one employee or to no-one (a bearer card).
Assign to an employee
- Who: card manager, super admin.
- Inputs: card(s) → employee(s) mapping; per-card policy (balance + reset, limits, CVM, funding source); activation variant (employee-claim ✅ / admin-full).
- Cost centers: the card inherits all the employee's cost center(s) and is kept in sync — no manual picker; if the employee has several, the default cost center is used for card payments.
- Steps: pick card(s) → map to employee(s) → apply policy/template → (optional) approval →
ISSUED → ASSIGNED→ trigger activation. - Rules: card must be
ISSUED; employee active; enforce the hard cap on cards per employee; bulk assign via CSV (cardToken → employee). - Edge cases: mismatched counts (more cards than employees); cap reached → clear error listing affected employees; duplicate assignment blocked.
Leave as a bearer card (unassigned)
- The card has no holder; anyone with the card who knows the PIN can use it, so its CVM is PIN (OTP needs a single registered holder — not available for bearer cards).
- Cost center: optional — a picker (shown only for bearer cards) links at most one cost center (not inherited).
- Steps: set policy (balance + reset, limits, optional cost center, funding source) → admin sets the PIN →
ISSUED → ACTIVE→ distribute the card + PIN to the intended users. - Use it for: shared/pool cards, petty cash, kiosks. Recommend stored-value or low balance + tight limits given the shared PIN.
Cost-center inheritance & sync (assigned cards)
An assigned card mirrors the employee's cost-center membership. If the employee is removed from a cost center, the card is removed from that cost center too. If the employee is added to a new cost center, the card inherits it.
3.6 Reassign / unassign
- Who: card manager, super admin.
- Reassign: move a card from employee A to B — card must be frozen; remaining balance is reclaimed to the company wallet by default (opt-in to carry over); inherited cost centers are re-derived from B; new activation for B.
- Unassign: remove the employee link → either return to the pool (
ACTIVE/… → ISSUED) or convert to a bearer card (holder = none), per the admin's choice; inherited cost centers are cleared (a bearer card may then be linked to one cost center); balance reclaimed to wallet when returning to the pool; PIN reset as appropriate. - Edge cases: pending transactions must settle first.
3.7 Activation (admin-driven)
- Who: card manager (assign) + employee (claim); admin full-activation; or admin bearer-activation.
- Employee-claim (recommended): employee proves possession (tap/scan/code) + OTP + sets own PIN →
ASSIGNED → ACTIVE. Admin can resend the claim invite and see status (Pending / Claimed / Expired). - Admin full-activation: admin sets a temporary PIN →
ACTIVE, forced PIN change on first use. - Bearer activation (unassigned): admin sets the card PIN (CVM = PIN) →
ISSUED → ACTIVE; distribute card + PIN. No employee claim. - UI needs: per-card/batch activation tracker; resend; claim-link expiry. (See card activation.)
3.8 Set / adjust card balance & reset (Layer 1)
- Who: card manager (within policy); increases may need finance/approver.
- Actions: allocate initial balance; top-up (always available); reduce; view remaining vs allocated + next reset date (if any); configure the reset.
- Reset configuration (per card/policy):
- Reset on a day of the month — the balance is replenished to its allocated amount on that day each month.
- No reset — the balance is not replenished; the manager tops up when it runs empty.
- Top-up is always available in both modes.
- Rules: when the card is wallet-funded, the balance is a spend limit drawn from the company wallet at spend time (wallet/credit must have headroom); when unfunded, the balance is stored value and a top-up moves real money onto the card. Increases above a threshold route to approval.
- Edge cases: reduce below already-spent; leftover reclaimed on cancel; no roll-over by default (reset replenishes to the allocated amount).
3.9 Set card limits & controls
- Who: card manager.
- Fields: per-transaction / daily / monthly caps; allowed vendors or categories; channel rules (enable/disable tap, printed-QR, manual-entry; contactless floor limit / CVM threshold); CVM (PIN or OTP); funding source (company wallet or none); time windows; freeze-on-inactivity (N days).
- Rules: tightening = immediate; loosening = approval. Apply individually or via a policy template.
3.10 Freeze / unfreeze
- Who: card manager, super admin (employee can self-freeze in the app).
- Effect:
ACTIVE ⇄ FROZEN, instant; a frozen card declines all payments. - Use: suspicion, employee on leave, lost-phone precaution.
3.11 Replace / reissue
- Who: card manager, super admin.
- Triggers: damaged, expiring, compromised.
- Steps: issue new card → carry over holder, policy, and limits; remaining balance reclaimed to wallet by default (opt-in to transfer to the new card) → old card
CANCELLED/killed → activate new card. - Edge cases: balance-move atomicity; physical reprint + shipping.
3.12 Report lost / stolen
- Who: card manager, super admin, employee.
- Effect: immediate permanent kill (
LOST), token unusable; offer auto-replace; alert + audit.
3.13 Cancel / terminate
- Who: card manager, super admin.
- Effect:
CANCELLED(terminal); reclaim remaining balance to the company wallet; used for offboarding. - Bulk: cancel/freeze all cards for a department or offboarded employees.
3.14 Expiry & renewal
- Auto-transition to
EXPIREDat expiry; renewal reminders (e.g. 30 days prior); one-click reissue.
3.15 CVM management (PIN or OTP)
- The card's CVM is PIN or OTP (one of two, never both), set per card/company.
- PIN: cardholder sets/resets it (app or web + OTP); admin never sees the PIN; admin can require a PIN reset.
- OTP: no PIN is set; each qualifying transaction is verified with a one-time code to the cardholder's registered channel (shared OTP service).
4. How a card fits the spending model
A company runs one operating model — monthly limit or cost center, never both. The card's card balance is a separate bucket that applies to card payments regardless of the model:
| Payment method | Layer 1 decremented | Notes |
|---|---|---|
| xperise card | card balance — plus cost center only under the cost-center model | Never touches the monthly limit. |
| Wallet / QR | the operating-model bucket: monthly limit or cost center | Whichever one the company runs. |
Under the monthly-limit model a cardholder can hold both a monthly limit (governing wallet/QR) and a card (spending its card balance) — the two never overlap.
Under the cost-center model, which cost center a card draws depends on assignment: an employee-assigned card uses the employee's default cost center (inherited; if the employee has several, the default one); a bearer card uses its optional single cost center (if none is linked, the payment draws only the card balance).
Layer 2 (funding) for a card is optional:
- Funding source = company wallet — the card balance is a spend limit; a payment is declined unless both the card balance (and the cost center, under the cost-center model) and the company wallet/credit cover it.
- Funding source = none — the card balance is stored value (prepaid) and is the money; a payment only checks the card balance (and cost center, under the cost-center model). No wallet is drawn.
5. Screens implied (for UI design)
- Card inventory — table + filters + bulk action bar
- Card detail — summary + balance/limits + txn history + action menu
- Order physical cards — wizard: quantity → personalization → shipping → review
- Issue virtual card — form + secure in-app reveal
- Assign cards — single form + bulk mapping / CSV, with hard-cap validation
- Activation tracker — per batch: claimed / pending / expired; resend
- Balance & limits editor — with period/reset controls + approval prompt on increases
- Freeze / Report-lost / Replace — confirmation modals with reason + balance-reclaim notice
- Bulk actions — assign / freeze / cancel / limit-change with review + approval
6. Roles & permissions (RBAC)
| Action | Super admin | Card manager | Finance/approver | Auditor |
|---|---|---|---|---|
| Order / issue / assign / activate | ✅ | ✅ | — | view |
| Freeze / lost / replace / cancel | ✅ | ✅ | — | view |
| Set balance / limits (tighten) | ✅ | ✅ | — | view |
| Approve balance/limit increase | ✅ | request | ✅ | view |
| View inventory / detail / txns | ✅ | ✅ | ✅ | ✅ |
7. Approvals, notifications, audit
- Approval (maker-checker): balance/limit increases, large physical orders, adding a funding source; configurable thresholds. See Approvals.
- Notifications: employee — card assigned / claim invite / activated / frozen / lost / expiring / balance reset; admin — order status, approval requests, low card balance, suspicious activity.
- Audit: every action logs actor, timestamp, card, before/after, reason — immutable.
8. API sketch (illustrative)
POST /v1/cards/orders # order physical batch
POST /v1/cards/virtual # issue virtual (in-app)
GET /v1/cards # inventory (filters, paging)
GET /v1/cards/{id} # detail + txns
POST /v1/cards/{id}/assign # → ASSIGNED (bulk: /cards/assign)
POST /v1/cards/{id}/unassign # → ISSUED, reclaim balance to wallet
POST /v1/cards/{id}/activate # admin-full / resend claim
PATCH /v1/cards/{id}/balance # allocate / top-up / reduce / set period
PATCH /v1/cards/{id}/controls # limits, vendors, channels, windows
POST /v1/cards/{id}/freeze | /unfreeze
POST /v1/cards/{id}/replace # reclaim-to-wallet default; opt-in transfer
POST /v1/cards/{id}/report-lost
POST /v1/cards/{id}/cancel # reclaim balance → wallet
Related
- Corporate Portal — where card management lives among the other modules.
- Card Payment — lifecycle, activation, and acceptance modes.
- Overview — the two-layer model behind card balance + company wallet.