Documentation

Cards

Issue virtual and physical cards, set spend limits, and manage controls.

Cards link a bank account to the Visa or Mastercard rails. Banking issues both virtual cards (number generated immediately, usable for online purchases or pushed to a digital wallet) and physical cards (printed and shipped to the cardholder). Both types are linked to a checking-style account and operate against its available balance.

Card issuing requires sponsor bank support. Some sponsors only support virtual; some support both. Both Visa and Mastercard branding are configurable per card via cardBrand.

Issuing a card

POST/banking/cardsJWT
FieldTypeDescription
bankAccountId*string

The funding account. Must be checking or business_checking and active.

cardType*'virtual' | 'physical'

Virtual cards are issued instantly. Physical cards ship and require activation.

cardBrand*'visa' | 'mastercard'

Network branding. Must match what your sponsor supports.

cardholderNamestring

Name as it appears on the card. Defaults to the holder's legal name.

dailySpendLimitnumber

Max spend per UTC day.

monthlySpendLimitnumber

Max spend per calendar month.

shippingAddressobject

Required for physical. { line1, city, state, postalCode, country }.

curl -X POST https://appengine.appmint.io/banking/cards \
  -H "orgid: $ORG" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "bankAccountId": "acc_abc",
    "cardType": "virtual",
    "cardBrand": "visa",
    "cardholderName": "Alice Doe",
    "dailySpendLimit": 500.00,
    "monthlySpendLimit": 5000.00
  }'

A virtual card returns immediately with full PAN and CVV in the response (one-time exposure — store it client-side or push to the cardholder's wallet straight away). A physical card returns metadata only; the PAN never leaves the card factory.

Card types

Virtual

  • PAN issued instantly.
  • Usable for e-commerce, recurring billing, and digital-wallet provisioning.
  • Can be replaced (re-issued with a new PAN) without shipping anything.
  • A common pattern is to issue one virtual card per merchant or vendor for fraud isolation.

Physical

  • Printed by the sponsor's card vendor.
  • Status is pending from issuance until activated.
  • Activation requires the cardholder to confirm the last 4 digits printed on the physical card.

Activation (physical only)

POST/banking/cards/{id}/activateJWT

Body: { last4: string }. Confirms the cardholder physically has the card. Until activation, the card cannot authorise transactions even with full PAN.

Virtual cards skip this step — they are active from issue.

Spend limits

PUT/banking/cards/{id}/limitsJWT

Update any of the four limits:

{
  "dailySpendLimit": 1000.00,
  "monthlySpendLimit": 10000.00,
  "perTransactionLimit": 500.00,
  "dailyAtmLimit": 300.00
}
LimitMeaning
dailySpendLimitTotal purchase + cash-back per UTC day.
monthlySpendLimitTotal per calendar month, resets at midnight UTC on the 1st.
perTransactionLimitMax single transaction.
dailyAtmLimitATM withdrawal cap per day.

Limits are enforced at authorisation time. A card with a $500 daily limit will decline the second of two $300 same-day transactions before the rail even sees it.

Card controls

Toggles that gate categories of transactions:

PUT/banking/cards/{id}/controlsJWT
{
  "atmEnabled": true,
  "onlineEnabled": true,
  "internationalEnabled": false,
  "contactlessEnabled": true
}
ControlEffect when false
atmEnabledATM withdrawals declined.
onlineEnabledCard-not-present (e-commerce) transactions declined.
internationalEnabledNon-domestic merchants declined.
contactlessEnabledNFC tap-to-pay declined; magstripe/chip still works.

Defaults vary by sponsor — typically all enabled. The cardholder dashboard can flip these in real time, useful for travel or fraud-suspicion lockdown.

Lifecycle

pending → active → frozen ↔ active
                  ↓
              cancelled (terminal)

Freeze and unfreeze

POST/banking/cards/{id}/freezeJWT

Body: { reason?: string }. A frozen card declines all authorisations but retains its number — useful for "I lost my card, but I might find it" cases. Customer-facing apps usually expose this as a toggle.

POST/banking/cards/{id}/unfreezeJWT

Restores active.

Cancel

POST/banking/cards/{id}/cancelJWT

Body: { reason: string }. Terminal — the card cannot be revived. Pending authorisations finish out, but no new authorisations succeed.

Replace

POST/banking/cards/{id}/replaceJWT
{
  "reason": "lost",
  "shippingAddress": { "line1": "100 Main St", "city": "Brooklyn", "state": "NY", "postalCode": "11201", "country": "US" }
}

reason is lost | stolen | damaged. Replacing a card cancels the old one (terminal) and issues a new card with a new PAN. The new card inherits the old card's limits and controls. For stolen cards, the platform also tags the cancellation with a fraud flag for downstream review.

Reads

GET/banking/cardsJWT

?accountId=acc_abc lists cards for a specific account; without it, returns aggregate stats.

GET/banking/cards/{id}JWT

Single card record with status, limits, controls, and last-4. Full PAN is never returned post-issuance — the only window is the original create response.

Authorisation flow

When a card is presented at a merchant:

  1. 1

    Authorisation request

    Network sends an authorisation message to the sponsor.

  2. 2

    Limit and control checks

    The platform's CardAuthorizationService checks: status, limits (daily, monthly, per-transaction), controls (ATM/online/international/contactless), and available balance on the linked account.

  3. 3

    Hold placement

    On approve, a hold equal to the auth amount is placed on the linked account. Available balance drops immediately.

  4. 4

    Settlement

    Hours to days later, the merchant captures. The hold converts to a posted debit. If the merchant doesn't capture, the hold expires (typically 7 days) and the balance is restored.

The card-authorisation service runs synchronously inside the request — it must respond within the network's authorisation window (typically under 2 seconds).

Stats

The list endpoint without accountId returns aggregate stats: total cards, by status, by type, by brand. Useful for admin dashboards.