---
title: "Issue a card"
method: POST
path: "/cards"
tags: ["Cards"]
---

# Issue a card

`POST /cards`

Issue a new card for a cardholder. Every card must be bound to at least one funding source at create time. The cardholder must have KYC status `APPROVED` before a card can be issued; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`.

New cards start in `state: "PENDING_ISSUE"` while the card issuer provisions the card. The `card.state_change` webhook fires on the transition to `ACTIVE` (or to `CLOSED` with `stateReason: "ISSUER_REJECTED"` if provisioning fails).

## Request body

- CardCreateRequest
  - `cardholderId` string, required — The id of the `Customer` to issue the card to. The customer must have KYC status `APPROVED`; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`.
  - `platformCardId` string — Optional platform-specific card identifier. System-generated when omitted, mirroring `platformCustomerId` semantics.
  - `form` 'VIRTUAL', required — Physical form factor of the card. Only `VIRTUAL` is supported in v1; `PHYSICAL` will be added in a later release.
  - `fundingSources` string[], required — Internal account ids to bind as funding sources, in priority order. The first entry is tried first by Authorization Decisioning. Every card must be bound to at least one source, and every source must belong to the cardholder and be denominated in a card-eligible currency (USDB in v1); otherwise the request is rejected with `FUNDING_SOURCE_INELIGIBLE`.

## Response `201`

Card issued successfully

- Card
  - `id` string, required — System-generated unique card identifier
  - `cardholderId` string, required — The id of the `Customer` who holds this card.
  - `platformCardId` string — Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics.
  - `state` 'PENDING_KYC' | 'PENDING_ISSUE' | 'ACTIVE' | 'FROZEN' | 'CLOSED', required — Lifecycle state of a card. | State | Description | |-------|-------------| | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | | `PENDING_ISSUE` | The card has been requested and is being provisioned with the issuer. | | `ACTIVE` | The card is live and can authorize transactions. | | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | | `CLOSED` | The card is permanently closed. Terminal, irreversible state. |
  - `stateReason` 'ISSUER_REJECTED' | 'CLOSED_BY_PLATFORM' | 'CLOSED_BY_GRID' — Reason a card reached a terminal or non-active state. Present on `CLOSED` cards, and on cards that fail provisioning before reaching `ACTIVE`. | Reason | Description | |--------|-------------| | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PENDING_ISSUE`. | | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). |
  - `brand` 'VISA' | 'MASTERCARD' — Card network brand. Read-only — determined by Grid when the card is provisioned with the issuer.
  - `form` 'VIRTUAL', required — Physical form factor of the card. Only `VIRTUAL` is supported in v1; `PHYSICAL` will be added in a later release.
  - `last4` string — Last four digits of the card PAN.
  - `expMonth` integer — Card expiration month (1–12).
  - `expYear` integer — Card expiration year (four digits).
  - `panEmbedUrl` string, uri — URL of the card issuer's iframe that securely displays the PAN, CVV, and expiry to the cardholder. The full PAN and CVV never cross Grid's servers — render this URL in an iframe in your client to reveal card details.
  - `fundingSources` string[], required — Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source.
  - `currency` string — Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency.
  - `issuerRef` string — Opaque identifier for the card on the underlying issuer. Useful for cross-referencing in issuer dashboards; not used for any Grid request routing.
  - `createdAt` string, date-time, required — Creation timestamp
  - `updatedAt` string, date-time, required — Last update timestamp

## Other responses

- `400` — Bad request. Returned with `CARDHOLDER_KYC_NOT_APPROVED` when the cardholder's KYC status is not `APPROVED`, with `FUNDING_SOURCE_INELIGIBLE` when the supplied funding source does not belong to the cardholder or is not denominated in a card-eligible currency, and for general invalid parameters.
- `401` — Unauthorized
- `500` — Internal service error
- `501` — Not implemented in this environment. Card issuance is not enabled for every Grid deployment; environments without a configured card issuer return `501 NOT_IMPLEMENTED`.

---

[API](https://skmtc.net/lightsparkdev/apis/grid-api.md) · [All operations](https://skmtc.net/lightsparkdev/apis/grid-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/lightsparkdev/grid-api/versions/d0bce562bffd/schema)
