Skip to main content

Documentation Index

Fetch the complete documentation index at: https://ramps-moonrise-limestone.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

A card is created with a single POST /cards request and progresses through a fixed lifecycle. This page covers the request shape, what happens after issuance, and the errors you should handle.

Request shape

curl -X POST "$GRID_BASE_URL/cards" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "cardholderId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "platformCardId": "card-emp-aary-001",
    "form": "VIRTUAL",
    "fundingSources": [
      "InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
    ]
  }'
FieldRequiredNotes
cardholderIdYesThe Customer that owns the card. Must be kycStatus: APPROVED.
platformCardIdNoYour own identifier. System-generated when omitted, mirroring platformCustomerId.
formYesVIRTUAL in v1. PHYSICAL will be added later.
fundingSourcesYesOrdered array of InternalAccount ids. Each must belong to the cardholder and share one card-eligible currency. The first entry is tried first by Authorization Decisioning.
The card’s currency is derived from the funding sources at issue time and surfaces on the returned Card resource — all bound sources share one currency.

The lifecycle

PENDING_ISSUE ──► ACTIVE ──► FROZEN ──► ACTIVE ──► CLOSED
       │             │                              ▲
       │             └──────────────────────────────┘

       └─► CLOSED (stateReason: ISSUER_REJECTED)
StateWhen you see it
PENDING_ISSUEReturned synchronously from POST /cards. The card cannot transact yet.
ACTIVEIssuer provisioned the card. Reached via CARD.STATE_CHANGE webhook.
FROZENYou called PATCH /cards/{id} with state: "FROZEN".
CLOSEDYou called DELETE /cards/{id} (or the issuer rejected provisioning). Terminal.
PENDING_KYC is also a valid state but you should not see it in v1 — issuance is gated on KYC up front.

After issuance

POST /cards returns immediately with state: "PENDING_ISSUE". The issuer provisions the card asynchronously; on success a CARD.STATE_CHANGE webhook fires with the activated Card resource including the populated last4, expMonth, expYear, and panEmbedUrl. If the issuer rejects provisioning, the same webhook fires with state: "CLOSED" and stateReason: "ISSUER_REJECTED". That card is terminal — issue a new one with a fresh platformCardId to retry.
Render panEmbedUrl in an iframe in your client to display the full PAN, CVV, and expiry to the cardholder. The full credentials never cross your servers.

Errors to handle

StatusCodeWhat it means
409CARDHOLDER_KYC_NOT_APPROVEDCardholder is not kycStatus: APPROVED. Drive KYC to completion before retrying.
409FUNDING_SOURCE_INELIGIBLEThe supplied internal account doesn’t belong to the cardholder or isn’t denominated in a card-eligible currency.
400INVALID_INPUTValidation failure on the request body.

Changing funding sources later

The bound funding sources can be replaced after issuance via PATCH /cards/{id} with a new fundingSources array. See Funding sources for the rules and the signed-retry flow.

Listing cards

curl -X GET "$GRID_BASE_URL/cards?cardholderId=Customer:019542f5-b3e7-1d02-0000-000000000001&limit=20" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
Filter by cardholderId, platformCardId, or state. The response is paginated using the standard cursor shape used by other Grid list endpoints.