Skip to content

Create and manage platform cards ​

Use createCard after the application is approved. This guide uses platform user authentication; partners should use partner card issuance.

Creating cards ​

The createCard mutation ​

graphql
mutation CreateCard($input: CreateCardInput!) {
  createCard(input: $input) {
    success
    id
    cardId
    cardType
    status
    last4
    expirationMonth
    expirationYear
    error
  }
}

Creating a virtual card ​

Virtual cards are available as soon as they are created.

json
{
  "input": {
    "cardApplicationId": 42,
    "cardType": "virtual",
    "limit": {
      "amount": 50000,
      "frequency": "per30DayPeriod"
    },
    "displayName": "JANE SMITH"
  }
}

Creating a physical card ​

Physical cards require a shipping address and phone number. The card ships to the provided address and must be activated upon receipt.

json
{
  "input": {
    "cardApplicationId": 42,
    "cardType": "physical",
    "limit": {
      "amount": 100000,
      "frequency": "per30DayPeriod"
    },
    "displayName": "JANE SMITH",
    "shipping": {
      "firstName": "Jane",
      "lastName": "Smith",
      "phoneNumber": "+15555551234",
      "line1": "123 Main St",
      "city": "Miami",
      "region": "FL",
      "postalCode": "33101",
      "countryCode": "US",
      "method": "standard"
    }
  }
}

Input fields ​

FieldTypeDescription
cardApplicationIdInt!ID of the approved card application
cardTypeCardType!"virtual" or "physical"
limitCardLimitInputSpending limit: { amount, frequency }
displayNameStringName printed on card (max 26 chars, alphanumeric + spaces + periods + hyphens). Immutable after creation.
shippingCardShippingInputRequired for physical cards. Ignored for virtual.
billingCardAddressInputBilling address. Defaults to shipping address if omitted.
sessionIdStringFrom generateEncryptionKeys (required if setting PIN)
encryptedPinStringPre-encrypted PIN (4-12 digits)

Spending limit frequencies ​

FrequencyDescription
per24HourPeriodRolling 24-hour window
per7DayPeriodRolling 7-day window
per30DayPeriodRolling 30-day window
perYearPeriodRolling 365-day window
perAuthorizationPer-transaction cap
allTimeLifetime total limit

Amounts in Cents

All limit amounts are in cents. 50000 = $500.00, 100000 = $1,000.00.

Card status lifecycle ​

StatusDescriptionReversible
notActivatedIssued but requires activation (physical cards)Yes
activeFully functional--
lockedTemporarily frozenYes (unfreeze)
canceledPermanently disabledNo

Card management ​

Freeze a card ​

Temporarily disable a card. The card cannot be used for transactions while frozen.

graphql
mutation FreezeCard($cardId: Int!) {
  freezeCard(cardId: $cardId) {
    success
    id
    cardId
    status
    error
  }
}

Unfreeze a card ​

Re-enable a frozen card.

graphql
mutation UnfreezeCard($cardId: Int!) {
  unfreezeCard(cardId: $cardId) {
    success
    id
    cardId
    status
    error
  }
}

Cancel a card ​

Permanently cancel a card. This action is irreversible.

graphql
mutation CancelCard($input: CancelCardInput!) {
  cancelCard(input: $input) {
    success
    id
    cardId
    status
    error
  }
}
json
{
  "input": {
    "cardId": 42,
    "reason": "No longer needed"
  }
}

Replace a virtual card ​

Generate a new card number for an existing virtual card. The old card is canceled automatically and the new card inherits spending limits.

graphql
mutation ReplaceVirtualCard($cardId: Int!) {
  replaceVirtualCard(cardId: $cardId) {
    success
    id
    oldCardId
    newCard {
      id
      type
      status
      last4
      expirationMonth
      expirationYear
    }
    error
  }
}

Replace any card (Lost/Stolen/Damaged) ​

Replace a virtual or physical card with a reason code. Physical card replacements require a shipping address.

graphql
mutation ReplaceCard($input: ReplaceCardInput!) {
  replaceCard(input: $input) {
    success
    id
    oldCardId
    newCard {
      id
      type
      status
      last4
      expirationMonth
      expirationYear
    }
    error
  }
}
json
{
  "input": {
    "cardId": 42,
    "reason": "lost",
    "shippingAddress": {
      "firstName": "Jane",
      "lastName": "Smith",
      "phoneNumber": "+15555551234",
      "line1": "123 Main St",
      "city": "Miami",
      "region": "FL",
      "postalCode": "33101",
      "countryCode": "US"
    }
  }
}

Replacement reasons: lost, stolen, damaged.

Update spending limit ​

graphql
mutation UpdateCardLimit($input: UpdateCardLimitInput!) {
  updateCardLimit(input: $input) {
    success
    id
    cardId
    limitAmount
    limitFrequency
    error
  }
}
json
{
  "input": {
    "cardId": 42,
    "limitAmount": 200000,
    "limitFrequency": "per30DayPeriod"
  }
}

Rename a card ​

Update the card's display nickname (max 26 characters).

graphql
mutation UpdateCardNickname($cardId: Int!, $nickname: String!) {
  updateCardNickname(cardId: $cardId, nickname: $nickname) {
    success
    id
    error
  }
}

PIN management ​

PINs are encrypted using RSA + AES-128-GCM. You must first generate an encryption session, then pass the sessionId with PIN operations.

Set or update PIN ​

graphql
mutation SetCardPin($input: SetCardPinInput!) {
  setCardPin(input: $input) {
    success
    id
    error
  }
}
json
{
  "input": {
    "cardId": 42,
    "sessionId": "session-id-from-generateEncryptionKeys",
    "encryptedPin": "encrypted-pin-value"
  }
}

PIN requirements: 4-12 digits, no repeated digits (e.g., 1111), no sequential patterns (e.g., 1234, 4321).

Reveal PIN ​

graphql
mutation GetCardPin($cardId: Int!, $sessionId: String!) {
  getCardPin(cardId: $cardId, sessionId: $sessionId) {
    success
    id
    encryptedPin
    error
  }
}

The response encryptedPin must be decrypted client-side using the session key.

Card secrets ​

Reveal the full card number (PAN), CVC, and expiry. Secrets are returned encrypted and must be decrypted client-side.

graphql
mutation RevealCardSecrets($cardId: Int!, $sessionId: String!) {
  revealCardSecrets(cardId: $cardId, sessionId: $sessionId) {
    success
    id
    encryptedSecrets
    error
  }
}

The encryptedSecrets field contains a JSON string that, when decrypted, yields:

json
{
  "pan": "4111111111111234",
  "cvc": "123",
  "expiry": { "month": "12", "year": "2028" }
}

Security

Never store decrypted card secrets. Only request them when absolutely necessary for display to the cardholder.

Listing cards ​

For partner integrations, use partner card queries.