Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@ grid receiver lookup-account <accountId>

```bash
# List cards
grid cards list [--cardholder-id <id>] [--state ACTIVE]
grid cards list [--customer-id <id>] [--state ACTIVE]

# Get a card
grid cards get <cardId>

# Issue a virtual card
grid cards create \
--cardholder-id <customerId> \
--customer-id <customerId> \
--funding-sources "InternalAccount:1,InternalAccount:2" \
--max-spend-per-transaction 5000

Expand Down
10 changes: 5 additions & 5 deletions cli/src/commands/cards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { parseList } from "../parse";

interface Card {
id: string;
cardholderId: string;
customerId: string;
platformCardId?: string;
state: "PENDING_KYC" | "PROCESSING" | "ACTIVE" | "FROZEN" | "CLOSED";
form: "VIRTUAL";
Expand Down Expand Up @@ -48,7 +48,7 @@ export function registerCardsCommand(
cardsCmd
.command("list")
.description("List cards")
.option("--cardholder-id <id>", "Filter by cardholder (customer) ID")
.option("--customer-id <id>", "Filter by customer ID")
.option("--account-id <id>", "Filter by a bound funding-source account ID")
.option("--platform-card-id <id>", "Filter by platform card ID")
.option("--state <state>", "Filter by state (PENDING_KYC, PROCESSING, ACTIVE, FROZEN, CLOSED)")
Expand All @@ -68,7 +68,7 @@ export function registerCardsCommand(
}

const params: Record<string, string | number | undefined> = {
cardholderId: options.cardholderId,
customerId: options.customerId,
accountId: options.accountId,
platformCardId: options.platformCardId,
state: options.state,
Expand Down Expand Up @@ -96,7 +96,7 @@ export function registerCardsCommand(
cardsCmd
.command("create")
.description("Issue a card")
.requiredOption("--cardholder-id <id>", "Cardholder (customer) ID")
.requiredOption("--customer-id <id>", "Customer ID of the cardholder")
.requiredOption("--funding-sources <list>", "Comma-separated internal account IDs, in priority order")
.option("--form <form>", "Card form (VIRTUAL)", "VIRTUAL")
.option("--platform-card-id <id>", "Your platform's identifier for the card")
Expand All @@ -118,7 +118,7 @@ export function registerCardsCommand(
}

const body: Record<string, unknown> = {
cardholderId: options.cardholderId,
customerId: options.customerId,
form: options.form,
fundingSources,
};
Expand Down
12 changes: 6 additions & 6 deletions cli/test/cards.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ describe("cards list", () => {
const { request } = await runCli([
"cards",
"list",
"--cardholder-id",
"--customer-id",
"Customer:abc",
"--state",
"ACTIVE",
]);

expect(request?.path).toBe("/grid/v1/cards");
expect(request?.query).toMatchObject({
cardholderId: "Customer:abc",
customerId: "Customer:abc",
state: "ACTIVE",
});
});
Expand All @@ -25,7 +25,7 @@ describe("cards create", () => {
const { request } = await runCli([
"cards",
"create",
"--cardholder-id",
"--customer-id",
"Customer:abc",
"--funding-sources",
"InternalAccount:1,InternalAccount:2",
Expand All @@ -34,7 +34,7 @@ describe("cards create", () => {
expect(request?.method).toBe("POST");
expect(request?.path).toBe("/grid/v1/cards");
expect(request?.body).toMatchObject({
cardholderId: "Customer:abc",
customerId: "Customer:abc",
form: "VIRTUAL",
fundingSources: ["InternalAccount:1", "InternalAccount:2"],
});
Expand All @@ -44,7 +44,7 @@ describe("cards create", () => {
const { request } = await runCli([
"cards",
"create",
"--cardholder-id",
"--customer-id",
"Customer:abc",
"--funding-sources",
"InternalAccount:1",
Expand All @@ -60,7 +60,7 @@ describe("cards create", () => {
runCli([
"cards",
"create",
"--cardholder-id",
"--customer-id",
"Customer:abc",
"--funding-sources",
"InternalAccount:1",
Expand Down
22 changes: 11 additions & 11 deletions mintlify/openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mintlify/snippets/cards/funding-sources.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ 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",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"form": "VIRTUAL",
"fundingSources": [
"InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
Expand Down
8 changes: 4 additions & 4 deletions mintlify/snippets/cards/issuing-cards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ 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",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"form": "VIRTUAL",
"fundingSources": [
"InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
Expand All @@ -22,7 +22,7 @@ curl -X POST "$GRID_BASE_URL/cards" \

| Field | Required | Notes |
|-------|----------|-------|
| `cardholderId` | Yes | The `Customer` that owns the card. Must be `kycStatus: APPROVED`. |
| `customerId` | Yes | The `Customer` that owns the card. Must be `kycStatus: APPROVED`. |
| `platformCardId` | No | Ignored if supplied. The value on the returned `Card` is generated by the server. |
| `form` | Yes | `VIRTUAL` in v1. `PHYSICAL` will be added later. |
| `fundingSources` | Yes | Ordered 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. |
Expand Down Expand Up @@ -107,10 +107,10 @@ and the signed-retry flow.
## Listing cards

```bash
curl -X GET "$GRID_BASE_URL/cards?cardholderId=Customer:019542f5-b3e7-1d02-0000-000000000001&limit=20" \
curl -X GET "$GRID_BASE_URL/cards?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001&limit=20" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

Filter by `cardholderId`, `platformCardId`, or `state`. The response is
Filter by `customerId`, `platformCardId`, or `state`. The response is
paginated using the standard cursor shape used by other Grid list
endpoints.
4 changes: 2 additions & 2 deletions mintlify/snippets/cards/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ 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",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"form": "VIRTUAL",
"fundingSources": [
"InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
Expand All @@ -60,7 +60,7 @@ supplied in the request is ignored. When activation completes, a
"timestamp": "2026-05-08T14:11:00Z",
"data": {
"id": "Card:019542f5-b3e7-1d02-0000-000000000010",
"cardholderId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"state": "ACTIVE",
"brand": "VISA",
"form": "VIRTUAL",
Expand Down
2 changes: 1 addition & 1 deletion mintlify/snippets/cards/sandbox-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ curl -X POST "$GRID_BASE_URL/cards" \
-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"cardholderId": "Customer:...",
"customerId": "Customer:...",
"form": "VIRTUAL",
"fundingSources": ["InternalAccount:..."]
}'
Expand Down
2 changes: 1 addition & 1 deletion mintlify/snippets/cards/webhooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ activation after issuance:
"timestamp": "2026-05-08T14:11:00Z",
"data": {
"id": "Card:019542f5-b3e7-1d02-0000-000000000010",
"cardholderId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"state": "ACTIVE",
"brand": "VISA",
"form": "VIRTUAL",
Expand Down
22 changes: 11 additions & 11 deletions openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions openapi/components/schemas/cards/Card.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
type: object
required:
- id
- cardholderId
- customerId
- state
- form
- fundingSources
Expand All @@ -15,7 +15,7 @@ properties:
type: string
description: System-generated unique card identifier
example: Card:019542f5-b3e7-1d02-0000-000000000010
cardholderId:
customerId:
type: string
description: The id of the `Customer` who holds this card.
example: Customer:019542f5-b3e7-1d02-0000-000000000001
Expand Down
4 changes: 2 additions & 2 deletions openapi/components/schemas/cards/CardCreateRequest.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
type: object
required:
- cardholderId
- customerId

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Breaking rename lacks versioning

This hard rename removes the required cardholderId request and response fields and the existing list filter while keeping the API on the same 2025-10-13 server path. Existing clients targeting that version can send invalid create requests, fail to deserialize cards, or silently receive unfiltered lists. This violates the repository directive that breaking changes must bump info.version and use a matching new servers.url; introduce the rename under a new API version.

Context Used: CLAUDE.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/cards/CardCreateRequest.yaml
Line: 3

Comment:
**Breaking rename lacks versioning**

This hard rename removes the required `cardholderId` request and response fields and the existing list filter while keeping the API on the same `2025-10-13` server path. Existing clients targeting that version can send invalid create requests, fail to deserialize cards, or silently receive unfiltered lists. This violates the repository directive that breaking changes must bump `info.version` and use a matching new `servers.url`; introduce the rename under a new API version.

**Context Used:** CLAUDE.md ([source](https://github.com/lightsparkdev/grid-api/blob/main/CLAUDE.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

- form
- fundingSources
properties:
cardholderId:
customerId:
type: string
description: >-
The id of the `Customer` to issue the card to. The customer must have
Expand Down
Loading
Loading