Cards: Virtual & Physical

This page covers everything about the Card object: the two independent status dimensions every card has, how virtual and physical issuance differ, activation, sensitive-data handling, PIN management, and how transaction limits cascade from Program to Cardholder to Card.

🚧

Only Cardholders with status = 1 (Approved) — see Cardholders & the Compliance Lifecycle — can have cards issued to them.

Virtual vs. physical, at a glance

VirtualPhysical
Issuance endpointPOST /cards/virtual/{cardholderId}POST /cards/assign/{cardholderId}
Required fieldsnameOnCardnameOnCard, cardType
Ready to use immediately?Yes — issuerCardStatus = 1 (Active) on issuanceNo — issuerCardStatus = 4 (Not Activated) until activated
Activation required?NoYes — PUT /cards/{cardId}/activate
Card design selection (cardType)?Not applicableYes — selects one of the Program's 6 design slots
Deposit addresses generated at issuance?YesYes

Two independent status dimensions

Every card has two separate status fields that are easy to conflate but represent different things:

  • cardStatus — the approval status of the issuance request itself
  • issuerCardStatus — the card's operational lifecycle after approval

cardStatus — approval

cardStatusMeaning
0Pending
1Approved
2Declined
stateDiagram-v2
    [*] --> Pending: Card issuance requested
    Pending --> Approved
    Pending --> Declined
    Approved --> [*]
    Declined --> [*]

issuerCardStatus — operational lifecycle

issuerCardStatusMeaning
0Pending
1Active
2On Hold
3Closed
4Not Activated
stateDiagram-v2
    [*] --> NotActivated: Physical card approved
    [*] --> Active: Virtual card approved
    NotActivated --> Active: PUT /cards/{cardId}/activate
    Active --> OnHold: PUT /cards/{cardId}/status — newStatus 2
    OnHold --> Active: PUT /cards/{cardId}/status — newStatus 1
    Active --> Closed
    OnHold --> Closed
    Closed --> [*]

Putting them together

cardStatusissuerCardStatusWhat it means
0 PendingIssuance request awaiting approval; no card exists yet
2 DeclinedIssuance request declined; no card was created
1 Approved4 Not ActivatedPhysical card approved and issued, awaiting cardholder activation
1 Approved1 ActiveCard ready to use — virtual immediately, or physical after activation
1 Approved2 On HoldCard temporarily blocked from transacting
1 Approved3 ClosedCard permanently closed
📘

GET /cards (the list endpoint) returns a single status field per card, using the same 0–4 values as issuerCardStatus. GET /cards/{cardId} (the detail endpoint) returns both cardStatus and issuerCardStatus separately. PUT /cards/{cardId}/status only accepts newStatus values 1 (Active) or 2 (On Hold) — 3 (Closed) and 4 (Not Activated) aren't reachable through this endpoint.

Issuing a virtual card

POST /cards/virtual/{cardholderId}
FieldRequiredDescription
nameOnCardYesName to appear on the virtual card (1–26 characters)
aliasNoA localized system alias to help distinguish between a cardholder's cards
transactionLimitNoCard-level spending ceiling (decimal-implied); inherits the Cardholder's limit if unset
callingCode, countryCallingCode, phoneNum, cellNum, emailAdrNoCard-specific contact details — see "The contact object" below

Issuing a physical card

POST /cards/assign/{cardholderId}
FieldRequiredDescription
nameOnCardYesName to appear on the physical card during personalization (1–26 characters)
cardTypeYes05 — selects a Card Design slot (see Card Programs & Designs). 0 is the Program's default design.
alias, transactionLimit, contact fieldsNoSame as virtual

The issuance response

Both issuance endpoints return a CardCreateResponse:

FieldDescription
statussuccess | error
cardIdThe new card's unique ID
typephysical | virtual
maskedCardNumberThe PAN, masked to the last 4 digits
cryptoAddressesGenerated immediately, even before a physical card is activated — see Funding & Deposits
📘

Deposit addresses exist from the moment a card is issued — a physical card can receive digital-asset deposits before it's ever activated. Activation governs the card's ability to be used for point-of-sale/online spending and PIN-based transactions, not whether it can receive funds.

Activation (physical cards only)

PUT /cards/{cardId}/activate
FieldRequiredDescription
cardNumberYesThe card's 16-digit PAN
expMonthYesExpiry month (MM)
expYearYesExpiry year
cvvYesThe card's CVV/CVC
newPinYesA new 4-digit PIN

This is the standard "enter the details printed on your card, plus choose a PIN" activation pattern — the cardholder provides the PAN/expiry/CVV from the physical card they received as proof of possession, while simultaneously setting their PIN.

The response (ActivationResponse) confirms newStatus = 1 (Active).

🚧

Activation is a one-way transition — there's no "deactivate" or "return to Not Activated" operation. To temporarily block a card after activation, use PUT /cards/{cardId}/status with newStatus = 2 (On Hold) instead.

Retrieving card data

EndpointReturnsSensitivity
GET /cardsList of cards (maskedCardNumber, status, cardholderId, names, createdDatetime)Low — safe for general listing UIs
GET /cards/{cardId}Full CardViewMaskedcardStatus, issuerCardStatus, alias, maskedCardNumber, transactionLimit, cryptoAddresses, contact, typeLow
GET /cards/{cardId}/detailsCardDetailsMaskedfull unmasked cardNumber, expMonth, expYear, cvv, plus cryptoAddressesCritical
GET /cards/{cardId}/statusCurrent status fields onlyLow
GET /cards/{cardId}/balanceledgerBalance, availableBalance, currency — see Accounts, Wallets & Deposit AddressesLow
❗️

GET /cards/{cardId}/details returns the complete PAN and CVV in plaintext, despite "Masked" in its schema name (CardDetailsMasked) — this naming does not reflect the actual response content. The full PAN and CVV are only exposed once the cardholder is compliance-approved (status = 1). Treat this endpoint as returning the most sensitive data available through this API:

  • Call it only when displaying full card details to the cardholder themselves (e.g. for manual entry into a digital wallet), and over connections/UIs that meet PCI-DSS requirements for PAN/CVV display.
  • Never log the response.
  • Never persist cardNumber or cvv in your own systems beyond the immediate use case.
  • See Security Compliance & Data Protection.

PIN management

PUT /cards/{cardId}/pin

Requires both oldPIN and newPIN — this is a change operation, not a reset. (The initial PIN is set during activation via newPin on the activate call above; virtual cards, which have no PIN-based point-of-sale use, may not require this at all.)

Updating card details

PUT /cards/{cardId}/update
FieldDescription
aliasUpdate the card's display alias
transactionLimitUpdate the card-level spending ceiling (decimal-implied, capped by the Cardholder's limit)
callingCode, countryCallingCode, phoneNum, cellNum, emailAdrUpdate card-specific contact details

The contact object

Each card carries its own optional contact object (calling code, phone numbers, email) — used, for example, as the delivery target for card-specific notifications. If not set, it defaults to the Cardholder's contact details. This is useful for corporate use cases where a shared corporate card might route notifications to a different contact than the individual Cardholder's personal details — see Program Architecture: Corporate use cases.

Transaction limit inheritance

transactionLimit cascades from Program → Cardholder → Card, with each level optional and capped by the level above:

flowchart TD
    P["Program transactionLimit<br/>(ceiling — cannot be exceeded by anything below)"]
    CH["Cardholder transactionLimit<br/>(optional — if unset, inherits Program's)"]
    C["Card transactionLimit<br/>(optional — if unset, inherits Cardholder's)"]
    P --> CH --> C

A Card's effective transaction limit is therefore the most specific limit set, falling back up the chain — but never exceeding the Program's ceiling, regardless of what's configured at the Cardholder or Card level.

What's next