Skip to content

remove the REFUNDED card transaction status from the spec - #909

Open
ls-bolt[bot] wants to merge 1 commit into
mainfrom
09-08-remove-refunded-card-status
Open

remove the REFUNDED card transaction status from the spec#909
ls-bolt[bot] wants to merge 1 commit into
mainfrom
09-08-remove-refunded-card-status

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

CardTransactionStatus carried a REFUNDED value the server has no code path to emit,
and WebhookType carried a matching CARD_TRANSACTION.REFUNDED event that is never
fired. A card transaction's status describes the settlement lifecycle only — a merchant
return is already reported by direction and refundedAmount, so a REFUNDED status
would double-encode a fact two fields carry.

This removes both values and corrects the prose that described the removed behavior.

What changed

Enums

  • CardTransactionStatus — dropped REFUNDED; four values remain (AUTHORIZED,
    PARTIALLY_SETTLED, SETTLED, EXCEPTION). The status table's SETTLED row now
    states that a later RETURN keeps the transaction SETTLED with the returned value
    in refundedAmount.
  • WebhookType and CardTransactionWebhook.type — dropped CARD_TRANSACTION.REFUNDED.

Corrected prose

  • Return-reversal simulator — this precondition was wrong, not merely stale. It said
    "the parent transaction must be in REFUNDED state", a state that cannot occur, so an
    integrator following it would test against something unreachable. It now says the
    parent must have a posted return (non-zero refundedAmount), which is what the
    endpoint actually gates on.
  • Return simulator and SandboxCardReturnRequest — a full return no longer "flips the
    parent to REFUNDED"; full and partial both keep it SETTLED with refundedAmount
    set.
  • Card-transaction webhook description — removed CARD_TRANSACTION.REFUNDED from the
    event list. It now describes the webhook as firing on every lifecycle update rather
    than every state transition, since a return changes no status: a repeated
    CARD_TRANSACTION.SETTLED is a new update, not a duplicate, and refundedAmount /
    refundSummary are what distinguish a return from the original settlement. The
    example payload previously carried
    type: CARD_TRANSACTION.REFUNDED / status: REFUNDED and now carries the settled
    shape with a non-zero refundedAmount.
  • CardTransaction.direction said "card transactions debit the customer's account",
    which is not true of a standalone merchant refund. It now describes both directions.
  • Card docs snippets — status diagram, status table, terminology, and sandbox testing.

Changelog — new September 2026 entry.

Scope note

TransactionStatus.REFUNDED is a different enum for cross-border payments and is still
live; it is untouched, as is the incoming-payment webhook note that references it.

Breaking-change check

oasdiff reports 17 errors, all request-property-enum-value-removed for the two
intended values. The count is inflated by fan-out: CARD_TRANSACTION.REFUNDED lives on
the shared BaseWebhook.type, so its removal is reported once per webhook path. There
are no other findings, and no warnings.

Removing a value a server never emits does not change any response a client has
received. Card issuance is gated per-platform, there is no production card history, and
status was never a stored column — it is re-derived on every read — so transactions
written before the redesign already report SETTLED rather than a stale REFUNDED.

Test plan

This is a spec + docs repo with no application code, so verification is the spec
toolchain:

  • npm run lint:openapi — exit 0. 901 problems / 0 errors / 179 warnings, byte-identical
    to the pre-change baseline, so nothing new was introduced.
  • npm run build:openapi — rebundled openapi.yaml and mintlify/openapi.yaml; the two
    are identical, and the bundle diff contains exactly the source edits (no stale-base
    drift).
  • markdownlint on every touched .mdx — same 5 pre-existing findings as on main,
    none from this change.
  • oasdiff breaking against origin/main — reviewed all 17 findings; each is one of the
    two intended enum removals.
  • Grepped REFUNDED across the repo and confirmed every remaining hit belongs to the
    cross-border TransactionStatus enum.

No client SDKs are checked into this repo — sdks/grid-typescript and sdks/grid-kotlin
are empty, and clients are generated by Stainless from the spec, which the preview CI
check builds on this PR.

@mintlify

mintlify Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Grid 🟢 Ready View Preview Sep 8, 2026, 6:57 AM

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
grid-flow-builder Ignored Ignored Preview Sep 8, 2026 7:07am UTC
grid-wallet-demo Ignored Ignored Preview Sep 8, 2026 7:07am UTC

Request Review

@ls-bolt ls-bolt Bot added the bolt label Sep 8, 2026
@github-actions github-actions Bot added the breaking-change Introduces a breaking change to the OpenAPI spec label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

oasdiff reports 17 error / 0 warning changes to openapi.yaml.
This PR will need approval from an API reviewer before merge.

Errors (17)

  • POST webhook:agent-action — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:agent-action — removed the enum value REFUNDED of the request property allOf[subschema #2]/data/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #3: Card Transaction]/status [request-property-enum-value-removed].
  • POST webhook:bulk-upload — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:card-funding-source-change — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:card-state-change — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:card-transaction — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:card-transaction — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[subschema #2]/type [request-property-enum-value-removed].
  • POST webhook:card-transaction — removed the enum value REFUNDED of the request property allOf[subschema #2]/data/status [request-property-enum-value-removed].
  • POST webhook:customer-update — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:external-account-status — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:incoming-payment — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:internal-account-status — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:invitation-claimed — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:outgoing-payment — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:test-webhook — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:verification-update — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].
  • POST webhook:wallet-operation — removed the enum value CARD_TRANSACTION.REFUNDED of the request property allOf[#/components/schemas/BaseWebhook]/type [request-property-enum-value-removed].

Detected by oasdiff. Full report: job summary or the oasdiff-report artifact.

Copy link
Copy Markdown

This stack of pull requests is managed by Graphite. Learn more about stacking.

@ls-bolt

ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@greptile review

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

docs(api): update return method description in sandbox card simulate

go

fix(types): remove REFUNDED enum value from card transaction status and webhook types

kotlin

fix(types): remove REFUNDED status and CARD_TRANSACTION_REFUNDED event from card transactions

openapi

fix(types): remove REFUNDED status, CARD_TRANSACTION.REFUNDED event

php

fix(types): remove REFUNDED status from CardTransaction and webhook event types

python

fix(types): remove REFUNDED status from CardTransaction and CardTransactionWebhookEvent

ruby

fix(types): remove REFUNDED status from CardTransaction and webhook event types

typescript

fix(types): remove REFUNDED status from CardTransaction and webhook types

Edit this comment to update them. They will appear in their respective SDK's changelogs.

grid-typescript studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ❗test ✅

npm install https://pkg.stainless.com/s/grid-typescript/b61eaa50acebc575ea5f1c467e94e70233704293/dist.tar.gz
grid-openapi studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️

grid-ruby studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

grid-kotlin studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ✅lint ✅test ❗

grid-go studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@d7a93bbcacc62a085bd70cf7617026903f3c87be
grid-python studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/e8dfb89ebd42658bd1ee5da0fd92d04a6226c79c/grid-0.0.1-py3-none-any.whl
grid-php studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅lint ✅test ✅

grid-cli studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ❗lint ❗test ❗


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-09-08 07:10:58 UTC

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the contract and documentation consistently reflect the server’s existing card-return behavior.

Summary

  • Card returns remain SETTLED, with return details represented by refundedAmount and refundSummary.
  • Return-related webhook deliveries reuse CARD_TRANSACTION.SETTLED.
  • Return-reversal documentation now requires a posted return rather than an unreachable status.
  • The previously ambiguous webhook guidance is fixed and its review thread is resolved.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[AUTHORIZED] --> P[PARTIALLY_SETTLED]
    A --> S[SETTLED]
    P --> S
    A --> E[EXCEPTION]
    P --> E
    S -->|Merchant RETURN| S
    S -->|Update refundedAmount and refundSummary| W[CARD_TRANSACTION.SETTLED webhook]
Loading

Comment thread openapi/webhooks/card-transaction.yaml Outdated
A card transaction's status tracks the settlement lifecycle only. A
merchant return is reported through direction and refundedAmount, so
REFUNDED double-encodes a fact two fields already carry — and the
server has no code path that emits it.

Drops REFUNDED from CardTransactionStatus and CARD_TRANSACTION.REFUNDED
from WebhookType, and corrects the prose that described the flip. The
return-reversal simulator's stated precondition was actively wrong: it
gates on a non-zero refundedAmount, not on a REFUNDED parent.

Co-Authored-By: aaryamanbhute <aaryamanbhute@users.noreply.github.com>
@ls-bolt
ls-bolt Bot force-pushed the 09-08-remove-refunded-card-status branch from 84dcf10 to 5d26886 Compare September 8, 2026 07:06
@ls-bolt

ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Revision log — updated in place, latest first.

Revision 1

  • Reworded the card-transaction webhook description per @greptile-apps: "every state transition" contradicted a return delivery that changes no state. It now says "every lifecycle update" and states explicitly that a repeated CARD_TRANSACTION.SETTLED is a new update rather than a duplicate, with refundedAmount / refundSummary as the fields that distinguish a return from the original settlement.
  • Verified: npm run lint:openapi exit 0, still 901 problems / 0 errors / 179 warnings — identical to the pre-change baseline.

@ls-bolt

ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

⚡ Review ledger

Round 1

  1. Webhook trigger is ambiguous — a return re-fires CARD_TRANSACTION.SETTLED with no status change, so "every state transition" could lead an integrator to drop it as a duplicate → FIXED: openapi/webhooks/card-transaction.yaml:4-18 — reworded to "every lifecycle update" plus an explicit paragraph on repeated SETTLED deliveries and reading refundedAmount / refundSummary to distinguish a return. Verified with npm run lint:openapi (exit 0, baseline-identical).

@ls-bolt

ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@greptile review

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

That revision addresses the ambiguity: “every lifecycle update” no longer implies that each delivery is a state transition, and it explicitly documents repeated CARD_TRANSACTION.SETTLED deliveries with refundedAmount / refundSummary distinguishing a return from the original settlement. With lint unchanged from the baseline, I have no further concerns.

@ls-bolt

ls-bolt Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

📌 Bolt Status

2026-09-08 18:36:00 UTC — ⚡ Agent glowing-witness-2(#2) started


Feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bolt breaking-change Introduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants