Skip to content
Draft
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
68 changes: 14 additions & 54 deletions openapi/paths/cards/cards_{id}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,17 @@ patch:
`state: CLOSED`.


Because both updates are sensitive state changes, this endpoint uses
Grid's 202 → signed-retry pattern (same shape as
`DELETE /auth/credentials/{id}` and `POST /internal-accounts/{id}/export`):


1. Call `PATCH /cards/{id}` with the target fields and no signing
headers. The response is `202` with a `payloadToSign`, `requestId`, and
`expiresAt`.


2. Sign the `payloadToSign` with the session private key of a verified
authentication credential on the card's owning internal account and
retry with the signature as the `Grid-Wallet-Signature` header and the
`requestId` echoed back as the `Request-Id` header. The signed retry
returns `200` with the updated `Card`.
This endpoint is authenticated by the platform credential alone and
returns `200` directly. It deliberately does not use Grid's 202 →
signed-retry pattern: that pattern signs with the session key of a
credential on the owning internal account, so it models actions taken
*by* the end user on their own credentials or funds. Freezing or
closing a card is routinely an action taken *about* a user and without
them present - fraud response, offboarding, an ops-driven freeze - and
requiring the cardholder's signature would make exactly those cases
impossible. Operations that expose sensitive card data
(`POST /cards/{id}/reveal`, 3DS password retrieval) are SCA-railed
instead, because there the cardholder is the party being served.


Effects:
Expand Down Expand Up @@ -118,30 +114,6 @@ patch:
- Cards
security:
- BasicAuth: []
parameters:
- name: Grid-Wallet-Signature
in: header
required: false
description: >-
Signature over the `payloadToSign` returned in a prior `202`
response, produced with the session private key of a verified
authentication credential on the card's owning internal account and
base64-encoded. Required on the signed retry; ignored on the initial
call.
schema:
type: string
example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE=
- name: Request-Id
in: header
required: false
description: >-
The `requestId` returned in a prior `202` response, echoed back on
the signed retry so the server can correlate it with the issued
challenge. Required on the signed retry; must be paired with
`Grid-Wallet-Signature`.
schema:
type: string
example: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21
requestBody:
required: true
content:
Expand Down Expand Up @@ -175,21 +147,11 @@ patch:
state: CLOSED
responses:
'200':
description: Signed retry accepted. Returns the updated card.
description: Card updated. Returns the updated card.
content:
application/json:
schema:
$ref: ../../components/schemas/cards/Card.yaml
'202':
description: >-
Challenge issued. The response contains a `payloadToSign` that must
be signed with the session private key of a verified authentication
credential on the card's owning internal account, along with a
`requestId` that must be echoed back on the retry.
content:
application/json:
schema:
$ref: ../../components/schemas/common/SignedRequestChallenge.yaml
'400':
description: >-
Bad request. Returned with `FUNDING_SOURCE_INELIGIBLE` when a
Expand All @@ -202,10 +164,8 @@ patch:
$ref: ../../components/schemas/errors/Error400.yaml
'401':
description: >-
Unauthorized. Returned when the provided `Grid-Wallet-Signature` is
missing, malformed, or does not match a pending update challenge for
this card, or when the `Request-Id` does not match an unexpired
pending challenge.
Unauthorized. Returned when the platform credential is missing or
invalid, or does not grant access to this card.
content:
application/json:
schema:
Expand Down
Loading