{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/api-evangelist/lightspark/main/json-schema/lightspark-card-schema.json",
  "title": "Card",
  "x-generated": "2026-10-12",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/lightspark-cards-api-openapi.yml#/components/schemas/Card",
  "type": "object",
  "required": [
    "id",
    "cardholderId",
    "state",
    "form",
    "fundingSources",
    "createdAt",
    "updatedAt"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "System-generated unique card identifier",
      "readOnly": true
    },
    "cardholderId": {
      "type": "string",
      "description": "The id of the `Customer` who holds this card."
    },
    "platformCardId": {
      "type": "string",
      "description": "Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics."
    },
    "state": {
      "$ref": "#/$defs/CardState"
    },
    "stateReason": {
      "anyOf": [
        {
          "$ref": "#/$defs/CardStateReason"
        },
        {
          "type": "null"
        }
      ],
      "description": "Reason associated with the current `state`. Populated when the card is `CLOSED` or when provisioning was rejected; otherwise null."
    },
    "brand": {
      "$ref": "#/$defs/CardBrand"
    },
    "form": {
      "$ref": "#/$defs/CardForm"
    },
    "last4": {
      "type": "string",
      "description": "Last four digits of the card PAN."
    },
    "expMonth": {
      "type": "integer",
      "minimum": 1,
      "maximum": 12,
      "description": "Card expiration month (1–12)."
    },
    "expYear": {
      "type": "integer",
      "description": "Card expiration year (four digits)."
    },
    "fundingSources": {
      "type": "array",
      "description": "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.",
      "items": {
        "type": "string"
      }
    },
    "currency": {
      "type": "string",
      "description": "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.",
      "readOnly": true
    },
    "processorRef": {
      "type": "string",
      "description": "Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing.",
      "readOnly": true
    },
    "issuerRef": {
      "type": "string",
      "description": "Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing.",
      "readOnly": true
    },
    "createdAt": {
      "type": "string",
      "format": "date-time",
      "description": "Creation timestamp",
      "readOnly": true
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time",
      "description": "Last update timestamp",
      "readOnly": true
    }
  },
  "$defs": {
    "CardBrand": {
      "type": "string",
      "enum": [
        "VISA",
        "MASTERCARD"
      ],
      "description": "Card network brand. Read-only — determined by Grid when the card is\nprovisioned with the issuer.\n"
    },
    "CardForm": {
      "type": "string",
      "enum": [
        "VIRTUAL"
      ],
      "description": "Physical form factor of the card. Only `VIRTUAL` is supported in v1;\n`PHYSICAL` will be added in a later release.\n"
    },
    "CardState": {
      "type": "string",
      "enum": [
        "PENDING_KYC",
        "PROCESSING",
        "ACTIVE",
        "FROZEN",
        "CLOSED"
      ],
      "description": "Lifecycle state of a card.\n\n| State | Description |\n|-------|-------------|\n| `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. |\n| `PROCESSING` | The card has been requested and is being provisioned with the issuer. |\n| `ACTIVE` | The card is live and can authorize transactions. |\n| `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. |\n| `CLOSED` | The card is permanently closed. Terminal, irreversible state. |\n"
    },
    "CardStateReason": {
      "type": "string",
      "enum": [
        "ISSUER_REJECTED",
        "CLOSED_BY_PLATFORM",
        "CLOSED_BY_GRID"
      ],
      "description": "Reason a card reached a terminal or non-active state. Present on\n`CLOSED` cards, and on cards that fail provisioning before reaching\n`ACTIVE`.\n\n| Reason | Description |\n|--------|-------------|\n| `ISSUER_REJECTED` | The card issuer rejected provisioning during `PROCESSING`. |\n| `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. |\n| `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). |\n"
    }
  }
}