From 5d268867801ff48ab6e448ce54df0f52bc63219a Mon Sep 17 00:00:00 2001 From: Aaryaman Bhute Date: Tue, 8 Sep 2026 06:51:01 +0000 Subject: [PATCH] remove the REFUNDED card transaction status from the spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- mintlify/changelog.mdx | 21 +++++++++++++ mintlify/openapi.yaml | 30 +++++++++---------- .../cards/implementation-overview.mdx | 6 ++-- mintlify/snippets/cards/reconciliation.mdx | 10 +++---- mintlify/snippets/cards/sandbox-testing.mdx | 4 +-- mintlify/snippets/cards/terminology.mdx | 6 ++-- openapi.yaml | 30 +++++++++---------- .../schemas/cards/CardTransaction.yaml | 5 +++- .../schemas/cards/CardTransactionStatus.yaml | 8 ++--- .../cards/SandboxCardReturnRequest.yaml | 4 +-- .../webhooks/CardTransactionWebhook.yaml | 1 - .../schemas/webhooks/WebhookType.yaml | 1 - .../sandbox_cards_{id}_simulate_return.yaml | 4 +-- ...x_cards_{id}_simulate_return_reversal.yaml | 11 +++---- openapi/webhooks/card-transaction.yaml | 19 ++++++++---- 15 files changed, 96 insertions(+), 64 deletions(-) diff --git a/mintlify/changelog.mdx b/mintlify/changelog.mdx index 0020a5767..9217a8a79 100644 --- a/mintlify/changelog.mdx +++ b/mintlify/changelog.mdx @@ -11,6 +11,27 @@ changes and roadmap, [book a live demo](https://www.lightspark.com/contact) or +## Card returns report as `SETTLED` with a `refundedAmount` + +`REFUNDED` is removed from `CardTransactionStatus`, and `CARD_TRANSACTION.REFUNDED` from +the webhook types. A card transaction's status tracks settlement only—a return is +reported through `direction` and `refundedAmount`, which together already carry it. + +- A settled purchase that the merchant later returns stays `SETTLED`, with the returned + value in `refundedAmount`. A standalone merchant refund arrives as `direction: CREDIT` + and `status: SETTLED`, with the credited value in `settledAmount`. +- Returns no longer get a webhook type of their own—the transaction re-fires + `CARD_TRANSACTION.SETTLED` with the updated amounts. +- The sandbox return reversal simulator requires a parent with a posted return (non-zero + `refundedAmount`) rather than a `REFUNDED` parent, which the previous docs described + and the server never produced. + +Nothing you have received changes: the status was always derived on read, so existing +transactions already report `SETTLED`. `TransactionStatus.REFUNDED` on cross-border +payments is a separate enum and is unaffected. + +See [Reconciliation](/cards/transactions/reconciliation). + ## Sandbox KYC and KYB follow the production flow Unregulated sandbox platforms now resolve a customer's verification from a submitted diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index d6b32d0f2..6b53862ce 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -9083,7 +9083,7 @@ paths: post: summary: Simulate a card return description: | - Simulate a merchant-initiated `RETURN` against an existing settled card transaction in the sandbox environment. Creates a `CardRefund` on the parent and either flips the parent to `REFUNDED` (full refund) or keeps it `SETTLED` with a non-zero `refundedAmount` (partial refund). + Simulate a merchant-initiated `RETURN` against an existing settled card transaction in the sandbox environment. Creates a `CardRefund` on the parent and keeps the parent `SETTLED` with the returned value in `refundedAmount`, whether the return is full or partial. Production returns `404` on this path. operationId: sandboxSimulateCardReturn @@ -9596,7 +9596,7 @@ paths: post: summary: Simulate a card return reversal description: | - Simulate a `RETURN_REVERSAL` against an existing `REFUNDED` card transaction in the sandbox environment — reversing a previously settled return. The parent transaction must be in `REFUNDED` state. The resulting card operation is delivered asynchronously via the issuer's events webhook. + Simulate a `RETURN_REVERSAL` against an existing card transaction in the sandbox environment — reversing a previously settled return. The parent transaction must have a posted return (non-zero `refundedAmount`). The resulting card operation is delivered asynchronously via the issuer's events webhook. Note: authorization reversal / void has no dedicated card-issuer simulate path (the void simulator emits a distinct `VOID` event), so — like authorization expiry — it is not exposed here. @@ -9622,7 +9622,7 @@ paths: $ref: '#/components/schemas/SandboxCardTransactionRefRequest' examples: returnReversal: - summary: Reverse a settled return on a refunded transaction + summary: Reverse a settled return on a transaction with a posted return value: cardTransactionId: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 responses: @@ -11681,7 +11681,9 @@ webhooks: post: summary: Card transaction description: | - Webhook that is called on every state transition of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), when settled funds are returned (`CARD_TRANSACTION.REFUNDED`), and when a pull or confirmation fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource. + Webhook that is called on every lifecycle update of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), and when a pull or confirmation fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource. + + Not every delivery changes `status`. A merchant return has no event type of its own: it re-fires `CARD_TRANSACTION.SETTLED` with the same status as the settlement that preceded it, and only the amounts move. Treat a repeated `CARD_TRANSACTION.SETTLED` as a new update rather than a duplicate, and read `refundedAmount` and `refundSummary` to tell a return apart from the original settlement. This endpoint should be implemented by clients of the Grid API. @@ -11795,11 +11797,11 @@ webhooks: lastEventAt: '2026-05-09T15:42:11Z' createdAt: '2026-05-09T10:00:00Z' updatedAt: '2026-05-09T15:42:11Z' - refunded: + returned: summary: Settled funds returned by the merchant value: id: Webhook:019542f5-b3e7-1d02-0000-000000000042 - type: CARD_TRANSACTION.REFUNDED + type: CARD_TRANSACTION.SETTLED timestamp: '2026-05-10T09:15:00Z' data: type: CARD @@ -11808,7 +11810,7 @@ webhooks: customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 18d3e5f7b4a9c2 issuerTransactionToken: lithic_txn_b81c2a4f - status: REFUNDED + status: SETTLED direction: DEBIT merchant: descriptor: BLUE BOTTLE COFFEE SF @@ -23607,17 +23609,17 @@ components: - AUTHORIZED - PARTIALLY_SETTLED - SETTLED - - REFUNDED - EXCEPTION description: | - Lifecycle status of a card transaction. + Lifecycle status of a card transaction. The status tracks settlement only — + a return is reported through `direction` and `refundedAmount`, not through a + status of its own. | Status | Description | |--------|-------------| | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | - | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | - | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | + | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. A `RETURN` received afterwards keeps the transaction `SETTLED` and reports the returned value in `refundedAmount`. | | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | CardMerchant: type: object @@ -23734,7 +23736,7 @@ components: $ref: '#/components/schemas/CardTransactionStatus' direction: $ref: '#/components/schemas/TransactionDirection' - description: Card transactions debit the customer's account. + description: A purchase is a `DEBIT`. A standalone merchant refund with no purchase to return against is a `CREDIT`, with the credited value in `settledAmount`. example: DEBIT merchant: $ref: '#/components/schemas/CardMerchant' @@ -26239,7 +26241,7 @@ components: required: - cardTransactionId - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and leaves the parent transaction `SETTLED` with the returned value in `refundedAmount`. properties: cardTransactionId: type: string @@ -27087,7 +27089,6 @@ components: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION - WALLET_OPERATION.COMPLETED - WALLET_OPERATION.FAILED @@ -27345,7 +27346,6 @@ components: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION WalletOperationCompletedData: title: Wallet Operation Completed Data diff --git a/mintlify/snippets/cards/implementation-overview.mdx b/mintlify/snippets/cards/implementation-overview.mdx index 03c878896..d36a7cf8b 100644 --- a/mintlify/snippets/cards/implementation-overview.mdx +++ b/mintlify/snippets/cards/implementation-overview.mdx @@ -63,8 +63,10 @@ Each authorization on a card produces a parent `CardTransaction` row. Children (pulls, clearings, refunds) are reconciled against the parent and rolled up into `pullSummary`, `settlementSummary`, and `refundSummary` aggregates. The lifecycle status moves -`AUTHORIZED → PARTIALLY_SETTLED → SETTLED → REFUNDED`, with -`EXCEPTION` as the failure path for stuck post-hoc pulls. +`AUTHORIZED → PARTIALLY_SETTLED → SETTLED`, with `EXCEPTION` as the +failure path for stuck post-hoc pulls. A merchant return keeps the +transaction `SETTLED` and reports the returned value in +`refundedAmount`. The full event model is covered in [Reconciliation](/cards/transactions/reconciliation). diff --git a/mintlify/snippets/cards/reconciliation.mdx b/mintlify/snippets/cards/reconciliation.mdx index bb4e3b4c4..fffb119a7 100644 --- a/mintlify/snippets/cards/reconciliation.mdx +++ b/mintlify/snippets/cards/reconciliation.mdx @@ -22,19 +22,19 @@ on the parent. ## Status transitions ```text - ┌─────────────────────────────────────┐ - │ ▼ -AUTHORIZED ──► PARTIALLY_SETTLED ──► SETTLED ──► REFUNDED +AUTHORIZED ──► PARTIALLY_SETTLED ──► SETTLED │ └──► EXCEPTION (pull failed after settlement) ``` +A merchant `RETURN` does not move the status. The transaction stays +`SETTLED` and the returned value appears in `refundedAmount`. + | Status | Meaning | |--------|---------| | `AUTHORIZED` | Auth approved, hold placed, no clearings yet. | | `PARTIALLY_SETTLED` | At least one clearing landed, but more are still expected (split shipments, multi-leg trips). | -| `SETTLED` | All clearings for the auth have posted. The transaction is closed against the funding source. | -| `REFUNDED` | A `RETURN` was received and the net settled amount has been refunded in full or part. | +| `SETTLED` | All clearings for the auth have posted. The transaction is closed against the funding source. A `RETURN` received afterwards keeps it `SETTLED` with the returned value in `refundedAmount`. | | `EXCEPTION` | The transaction settled to the network but the corresponding pull from the funding source failed. | Every transition is delivered via the generic transaction webhook diff --git a/mintlify/snippets/cards/sandbox-testing.mdx b/mintlify/snippets/cards/sandbox-testing.mdx index d9c175c15..45a0c286a 100644 --- a/mintlify/snippets/cards/sandbox-testing.mdx +++ b/mintlify/snippets/cards/sandbox-testing.mdx @@ -100,8 +100,8 @@ curl -X POST "$GRID_BASE_URL/sandbox/cards/Card:019542f5-b3e7-1d02-0000-00000000 }' ``` -A full refund flips the parent to `REFUNDED`; a partial refund keeps -it `SETTLED` with a non-zero `refundedAmount`. +A refund keeps the parent `SETTLED` with a non-zero `refundedAmount`, +whether it is full or partial. ## End-to-end happy path diff --git a/mintlify/snippets/cards/terminology.mdx b/mintlify/snippets/cards/terminology.mdx index 33db0624e..2bb74cc5b 100644 --- a/mintlify/snippets/cards/terminology.mdx +++ b/mintlify/snippets/cards/terminology.mdx @@ -43,9 +43,9 @@ land. ## Refund A merchant-initiated `RETURN` against a settled transaction. Refunds -flow back to the funding source. A full refund moves the parent -transaction to `REFUNDED`; a partial refund keeps it `SETTLED` with a -non-zero `refundedAmount`. +flow back to the funding source. A refund keeps the parent transaction +`SETTLED` and reports the returned value in `refundedAmount`, whether +it is full or partial. ## Exception diff --git a/openapi.yaml b/openapi.yaml index d6b32d0f2..6b53862ce 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -9083,7 +9083,7 @@ paths: post: summary: Simulate a card return description: | - Simulate a merchant-initiated `RETURN` against an existing settled card transaction in the sandbox environment. Creates a `CardRefund` on the parent and either flips the parent to `REFUNDED` (full refund) or keeps it `SETTLED` with a non-zero `refundedAmount` (partial refund). + Simulate a merchant-initiated `RETURN` against an existing settled card transaction in the sandbox environment. Creates a `CardRefund` on the parent and keeps the parent `SETTLED` with the returned value in `refundedAmount`, whether the return is full or partial. Production returns `404` on this path. operationId: sandboxSimulateCardReturn @@ -9596,7 +9596,7 @@ paths: post: summary: Simulate a card return reversal description: | - Simulate a `RETURN_REVERSAL` against an existing `REFUNDED` card transaction in the sandbox environment — reversing a previously settled return. The parent transaction must be in `REFUNDED` state. The resulting card operation is delivered asynchronously via the issuer's events webhook. + Simulate a `RETURN_REVERSAL` against an existing card transaction in the sandbox environment — reversing a previously settled return. The parent transaction must have a posted return (non-zero `refundedAmount`). The resulting card operation is delivered asynchronously via the issuer's events webhook. Note: authorization reversal / void has no dedicated card-issuer simulate path (the void simulator emits a distinct `VOID` event), so — like authorization expiry — it is not exposed here. @@ -9622,7 +9622,7 @@ paths: $ref: '#/components/schemas/SandboxCardTransactionRefRequest' examples: returnReversal: - summary: Reverse a settled return on a refunded transaction + summary: Reverse a settled return on a transaction with a posted return value: cardTransactionId: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 responses: @@ -11681,7 +11681,9 @@ webhooks: post: summary: Card transaction description: | - Webhook that is called on every state transition of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), when settled funds are returned (`CARD_TRANSACTION.REFUNDED`), and when a pull or confirmation fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource. + Webhook that is called on every lifecycle update of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), and when a pull or confirmation fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource. + + Not every delivery changes `status`. A merchant return has no event type of its own: it re-fires `CARD_TRANSACTION.SETTLED` with the same status as the settlement that preceded it, and only the amounts move. Treat a repeated `CARD_TRANSACTION.SETTLED` as a new update rather than a duplicate, and read `refundedAmount` and `refundSummary` to tell a return apart from the original settlement. This endpoint should be implemented by clients of the Grid API. @@ -11795,11 +11797,11 @@ webhooks: lastEventAt: '2026-05-09T15:42:11Z' createdAt: '2026-05-09T10:00:00Z' updatedAt: '2026-05-09T15:42:11Z' - refunded: + returned: summary: Settled funds returned by the merchant value: id: Webhook:019542f5-b3e7-1d02-0000-000000000042 - type: CARD_TRANSACTION.REFUNDED + type: CARD_TRANSACTION.SETTLED timestamp: '2026-05-10T09:15:00Z' data: type: CARD @@ -11808,7 +11810,7 @@ webhooks: customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 18d3e5f7b4a9c2 issuerTransactionToken: lithic_txn_b81c2a4f - status: REFUNDED + status: SETTLED direction: DEBIT merchant: descriptor: BLUE BOTTLE COFFEE SF @@ -23607,17 +23609,17 @@ components: - AUTHORIZED - PARTIALLY_SETTLED - SETTLED - - REFUNDED - EXCEPTION description: | - Lifecycle status of a card transaction. + Lifecycle status of a card transaction. The status tracks settlement only — + a return is reported through `direction` and `refundedAmount`, not through a + status of its own. | Status | Description | |--------|-------------| | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | - | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | - | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | + | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. A `RETURN` received afterwards keeps the transaction `SETTLED` and reports the returned value in `refundedAmount`. | | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | CardMerchant: type: object @@ -23734,7 +23736,7 @@ components: $ref: '#/components/schemas/CardTransactionStatus' direction: $ref: '#/components/schemas/TransactionDirection' - description: Card transactions debit the customer's account. + description: A purchase is a `DEBIT`. A standalone merchant refund with no purchase to return against is a `CREDIT`, with the credited value in `settledAmount`. example: DEBIT merchant: $ref: '#/components/schemas/CardMerchant' @@ -26239,7 +26241,7 @@ components: required: - cardTransactionId - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and leaves the parent transaction `SETTLED` with the returned value in `refundedAmount`. properties: cardTransactionId: type: string @@ -27087,7 +27089,6 @@ components: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION - WALLET_OPERATION.COMPLETED - WALLET_OPERATION.FAILED @@ -27345,7 +27346,6 @@ components: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION WalletOperationCompletedData: title: Wallet Operation Completed Data diff --git a/openapi/components/schemas/cards/CardTransaction.yaml b/openapi/components/schemas/cards/CardTransaction.yaml index 87caed2fa..6bcacdf1f 100644 --- a/openapi/components/schemas/cards/CardTransaction.yaml +++ b/openapi/components/schemas/cards/CardTransaction.yaml @@ -54,7 +54,10 @@ properties: $ref: ./CardTransactionStatus.yaml direction: $ref: ../transactions/TransactionDirection.yaml - description: Card transactions debit the customer's account. + description: >- + A purchase is a `DEBIT`. A standalone merchant refund with no purchase + to return against is a `CREDIT`, with the credited value in + `settledAmount`. example: DEBIT merchant: $ref: ./CardMerchant.yaml diff --git a/openapi/components/schemas/cards/CardTransactionStatus.yaml b/openapi/components/schemas/cards/CardTransactionStatus.yaml index 01be9d92c..786faae60 100644 --- a/openapi/components/schemas/cards/CardTransactionStatus.yaml +++ b/openapi/components/schemas/cards/CardTransactionStatus.yaml @@ -3,15 +3,15 @@ enum: - AUTHORIZED - PARTIALLY_SETTLED - SETTLED - - REFUNDED - EXCEPTION description: | - Lifecycle status of a card transaction. + Lifecycle status of a card transaction. The status tracks settlement only — + a return is reported through `direction` and `refundedAmount`, not through a + status of its own. | Status | Description | |--------|-------------| | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | - | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | - | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | + | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. A `RETURN` received afterwards keeps the transaction `SETTLED` and reports the returned value in `refundedAmount`. | | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | diff --git a/openapi/components/schemas/cards/SandboxCardReturnRequest.yaml b/openapi/components/schemas/cards/SandboxCardReturnRequest.yaml index e64a99795..e1d997a53 100644 --- a/openapi/components/schemas/cards/SandboxCardReturnRequest.yaml +++ b/openapi/components/schemas/cards/SandboxCardReturnRequest.yaml @@ -5,8 +5,8 @@ required: description: >- Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, - which creates a `CardRefund` and pushes the parent transaction towards - `REFUNDED` (full) or keeps it `SETTLED` (partial). + which creates a `CardRefund` and leaves the parent transaction `SETTLED` + with the returned value in `refundedAmount`. properties: cardTransactionId: type: string diff --git a/openapi/components/schemas/webhooks/CardTransactionWebhook.yaml b/openapi/components/schemas/webhooks/CardTransactionWebhook.yaml index 0d46e69d5..ef083d799 100644 --- a/openapi/components/schemas/webhooks/CardTransactionWebhook.yaml +++ b/openapi/components/schemas/webhooks/CardTransactionWebhook.yaml @@ -12,5 +12,4 @@ allOf: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION diff --git a/openapi/components/schemas/webhooks/WebhookType.yaml b/openapi/components/schemas/webhooks/WebhookType.yaml index 0d7da939d..c16199b7d 100644 --- a/openapi/components/schemas/webhooks/WebhookType.yaml +++ b/openapi/components/schemas/webhooks/WebhookType.yaml @@ -41,7 +41,6 @@ enum: - CARD_TRANSACTION.AUTHORIZED - CARD_TRANSACTION.PARTIALLY_SETTLED - CARD_TRANSACTION.SETTLED - - CARD_TRANSACTION.REFUNDED - CARD_TRANSACTION.EXCEPTION - WALLET_OPERATION.COMPLETED - WALLET_OPERATION.FAILED diff --git a/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml b/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml index 195fd41c9..68eba554e 100644 --- a/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml +++ b/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml @@ -3,8 +3,8 @@ post: description: > Simulate a merchant-initiated `RETURN` against an existing settled card transaction in the sandbox environment. Creates a `CardRefund` on - the parent and either flips the parent to `REFUNDED` (full refund) or - keeps it `SETTLED` with a non-zero `refundedAmount` (partial refund). + the parent and keeps the parent `SETTLED` with the returned value in + `refundedAmount`, whether the return is full or partial. Production returns `404` on this path. diff --git a/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml b/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml index 030d87076..f43a79d6a 100644 --- a/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml +++ b/openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml @@ -1,10 +1,11 @@ post: summary: Simulate a card return reversal description: > - Simulate a `RETURN_REVERSAL` against an existing `REFUNDED` card - transaction in the sandbox environment — reversing a previously settled - return. The parent transaction must be in `REFUNDED` state. The resulting - card operation is delivered asynchronously via the issuer's events webhook. + Simulate a `RETURN_REVERSAL` against an existing card transaction in the + sandbox environment — reversing a previously settled return. The parent + transaction must have a posted return (non-zero `refundedAmount`). The + resulting card operation is delivered asynchronously via the issuer's + events webhook. Note: authorization reversal / void has no dedicated card-issuer simulate @@ -34,7 +35,7 @@ post: $ref: ../../../components/schemas/cards/SandboxCardTransactionRefRequest.yaml examples: returnReversal: - summary: Reverse a settled return on a refunded transaction + summary: Reverse a settled return on a transaction with a posted return value: cardTransactionId: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 responses: diff --git a/openapi/webhooks/card-transaction.yaml b/openapi/webhooks/card-transaction.yaml index 5a9a054bb..28f586cb7 100644 --- a/openapi/webhooks/card-transaction.yaml +++ b/openapi/webhooks/card-transaction.yaml @@ -1,15 +1,22 @@ post: summary: Card transaction description: > - Webhook that is called on every state transition of a card + Webhook that is called on every lifecycle update of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it - (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), - when settled funds are returned (`CARD_TRANSACTION.REFUNDED`), and + (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), and when a pull or confirmation fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource. + Not every delivery changes `status`. A merchant return has no event type + of its own: it re-fires `CARD_TRANSACTION.SETTLED` with the same status as + the settlement that preceded it, and only the amounts move. Treat a + repeated `CARD_TRANSACTION.SETTLED` as a new update rather than a + duplicate, and read `refundedAmount` and `refundSummary` to tell a return + apart from the original settlement. + + This endpoint should be implemented by clients of the Grid API. @@ -132,11 +139,11 @@ post: lastEventAt: '2026-05-09T15:42:11Z' createdAt: '2026-05-09T10:00:00Z' updatedAt: '2026-05-09T15:42:11Z' - refunded: + returned: summary: Settled funds returned by the merchant value: id: Webhook:019542f5-b3e7-1d02-0000-000000000042 - type: CARD_TRANSACTION.REFUNDED + type: CARD_TRANSACTION.SETTLED timestamp: '2026-05-10T09:15:00Z' data: type: CARD @@ -145,7 +152,7 @@ post: customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 18d3e5f7b4a9c2 issuerTransactionToken: lithic_txn_b81c2a4f - status: REFUNDED + status: SETTLED direction: DEBIT merchant: descriptor: BLUE BOTTLE COFFEE SF