Skip to content
Merged
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
33 changes: 31 additions & 2 deletions mintlify/openapi.yaml

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

33 changes: 31 additions & 2 deletions openapi.yaml

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

31 changes: 30 additions & 1 deletion openapi/components/schemas/cards/CardUpdateRequest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ type: object
description: >-
Update request for `PATCH /cards/{id}`. At least one of `status`,
`fundingSource`, `maxSpendPerTransaction`, `maxSpendPerDay`, or
`maxTransactionsPerDay` must be supplied. `status`
`maxTransactionsPerDay` must be supplied. Supplying `status` also requires
`substatus` and `reason`, so every card state change carries why it
happened. `status`
transitions are limited to `ACTIVE ⇄ FROZEN` and
`ACTIVE | FROZEN → CLOSED`; any other transition returns
`409 INVALID_STATE_TRANSITION`. `CLOSED` is terminal and irreversible and
Expand All @@ -21,6 +23,33 @@ properties:
terminal and irreversible; once closed, the card stays in the
system for audit and reconciliation but cannot transact again.
example: FROZEN
substatus:
type: string
enum:
- LOST
- COMPROMISED
- DAMAGED
- END_USER_REQUEST
- ISSUER_REQUEST
- NOT_ACTIVE
- SUSPICIOUS_ACTIVITY
- INTERNAL_REVIEW
- EXPIRED
- UNDELIVERABLE
- OTHER
description: >-
Why the card is moving, in the card issuer's vocabulary. Required
whenever `status` is supplied, and forwarded to the issuer. Pick
`OTHER` when none of the named values fit and say why in `reason`.
example: SUSPICIOUS_ACTIVITY
reason:
type: string
minLength: 1
description: >-
A short sentence naming why the card is moving. Required whenever
`status` is supplied, and recorded against the card so a later reader
can tell why it changed.
example: Cardholder reported the card stolen.
Comment on lines +26 to +52

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 Conditional fields remain optional

When a caller supplies only status, the machine-readable schema still considers the request valid because substatus and reason are optional properties. The endpoint then rejects that request with 400 INVALID_INPUT, so OpenAPI validators and generated clients can accept or construct requests that are guaranteed to fail at runtime. Encode the dependency in the schema so both fields are required whenever status is present.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/cards/CardUpdateRequest.yaml
Line: 26-52

Comment:
**Conditional fields remain optional**

When a caller supplies only `status`, the machine-readable schema still considers the request valid because `substatus` and `reason` are optional properties. The endpoint then rejects that request with `400 INVALID_INPUT`, so OpenAPI validators and generated clients can accept or construct requests that are guaranteed to fail at runtime. Encode the dependency in the schema so both fields are required whenever `status` is present.

---

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Valid, and #1013 merged ~30s after you posted, so it went in unaddressed — follow-up in #1014 adding dependentRequired: {status: [substatus, reason]} (JSON Schema 2020-12, which 3.1 already uses). Verified with ajv that status-only and each half-supplied variant now fail, while requests without status still pass.


🤖 molten-solenoid(#1) | Feedback

fundingSource:
type: string
description: >-
Expand Down
13 changes: 11 additions & 2 deletions openapi/paths/cards/cards_{id}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,14 @@ patch:
summary: Freeze an active card
value:
status: FROZEN
substatus: SUSPICIOUS_ACTIVITY
reason: Unrecognised charges reported by the cardholder.
unfreeze:
summary: Unfreeze a frozen card
value:
status: ACTIVE
substatus: ISSUER_REQUEST
reason: Review closed with no action.
updateFundingSource:
summary: Replace the card's bound funding source
value:
Expand All @@ -181,11 +185,15 @@ patch:
summary: Freeze the card and replace its funding source in one call
value:
status: FROZEN
substatus: SUSPICIOUS_ACTIVITY
reason: Unrecognised charges reported by the cardholder.
fundingSource: InternalAccount:019542f5-b3e7-1d02-0000-000000000003
close:
summary: Permanently close the card
value:
status: CLOSED
substatus: END_USER_REQUEST
reason: Cardholder asked us to close the card.
responses:
'200':
description: Card updated. Returns the updated card.
Expand All @@ -199,8 +207,9 @@ patch:
supplied funding source does not belong to the cardholder or is
not denominated in the card's currency, with `INVALID_INPUT` when
`fundingSource` is combined with any `status` change on a card program
where the card issuer makes authorization decisions, and for general
invalid parameters.
where the card issuer makes authorization decisions, with
`INVALID_INPUT` when `status` is supplied without `substatus` or
without a non-empty `reason`, and for general invalid parameters.
content:
application/json:
schema:
Expand Down
Loading