feat: add granular counterparty payout failure reasons#689
Conversation
Add 7 counterparty (payout-side) reasons to OutgoingTransactionFailureReason so integrators can act on why a payout partner rejected or failed a transaction, rather than collapsing everything into the generic COUNTERPARTY_POST_TX_FAILED: - COUNTERPARTY_COMPLIANCE_REJECTED - COUNTERPARTY_ACCOUNT_INVALID - COUNTERPARTY_ACCOUNT_CANNOT_RECEIVE - COUNTERPARTY_LIMIT_EXCEEDED - COUNTERPARTY_PAYOUT_RETURNED - COUNTERPARTY_CURRENCY_EXCHANGE_FAILED - COUNTERPARTY_PAYOUT_EXPIRED Also document each value's customer-facing meaning in a markdown table, matching the OutgoingTransactionStatus convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename granular counterparty payout reasons (drop COUNTERPARTY_ prefix), remove COUNTERPARTY_CURRENCY_EXCHANGE_FAILED and COUNTERPARTY_PAYOUT_EXPIRED, and add EXECUTION_FAILED_POST_DEBIT, SETTLEMENT_FAILED, TIMEOUT, MANUAL_REFUND, and LSP_OPERATIONAL_FAILURE. Mark LIGHTNING_PAYMENT_FAILED and COUNTERPARTY_POST_TX_FAILED as deprecated/legacy. Update transaction lifecycle and error handling docs accordingly. Co-authored-by: Cursor <cursoragent@cursor.com>
Align the MDX failure-reason references with OutgoingTransactionFailureReason: drop the non-existent INSUFFICIENT_BALANCE, add TIMEOUT and MANUAL_REFUND (plus SETTLEMENT_FAILED in the error-handling snippet), reorder to enum order, and fix the FAILED webhook example to use ACCOUNT_INVALID. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Greptile SummaryAdds granular counterparty payout failure reasons to the
Confidence Score: 4/5Safe to merge; changes are additive enum expansions with consistent spec and doc updates, and no logic or runtime code is modified. All three documentation surfaces are updated consistently and the enum values are well-described. The only gaps are in the error-handling snippet: the getUserFriendlyMessage code example still maps the old INVALID_BANK_ACCOUNT key without adding ACCOUNT_INVALID, and there is no note warning developers about deprecated values they may still receive for historical transactions. mintlify/snippets/error-handling.mdx — the getUserFriendlyMessage example and the missing deprecated-values note
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/transactions/OutgoingTransactionFailureReason.yaml | Adds 8 new enum values and deprecates LIGHTNING_PAYMENT_FAILED and COUNTERPARTY_POST_TX_FAILED via description text. Descriptions are clear and accurate. |
| openapi.yaml | Bundle file updated in sync with OutgoingTransactionFailureReason.yaml; changes are identical. No issues found. |
| mintlify/openapi.yaml | Mintlify-specific bundle updated identically to openapi.yaml; properly kept in sync. |
| mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx | Failure reasons table updated to match the full enum, INSUFFICIENT_BALANCE removed, deprecated values relegated to a prose note, and the FAILED webhook example corrected from INVALID_BANK_ACCOUNT to ACCOUNT_INVALID. |
| mintlify/snippets/error-handling.mdx | New failure reasons added to the bullet list; however, the getUserFriendlyMessage code example still maps INVALID_BANK_ACCOUNT without ACCOUNT_INVALID, and there is no callout about deprecated values that may still arrive for historical transactions. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Outgoing Transaction] --> B{Status}
B -->|COMPLETED| C[Done]
B -->|FAILED| D{failureReason}
D --> E[Quote / Execution]
D --> F[Settlement]
D --> G[Funding]
D --> H[Operational]
D --> I[Payout Partner]
E --> E1[QUOTE_EXPIRED]
E --> E2[QUOTE_EXECUTION_FAILED]
E --> E3[EXECUTION_FAILED_POST_DEBIT]
F --> F1[SETTLEMENT_FAILED]
F --> F2[TIMEOUT]
G --> G1[FUNDING_AMOUNT_MISMATCH]
G --> G2[MANUAL_REFUND]
H --> H1[LSP_OPERATIONAL_FAILURE]
I --> I1[PAYOUT_RETURNED]
I --> I2[LIMIT_EXCEEDED]
I --> I3[ACCOUNT_CANNOT_RECEIVE]
I --> I4[ACCOUNT_INVALID]
I --> I5[COMPLIANCE_REJECTED]
I --> I6[COUNTERPARTY_POST_TX_FAILED deprecated]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Outgoing Transaction] --> B{Status}
B -->|COMPLETED| C[Done]
B -->|FAILED| D{failureReason}
D --> E[Quote / Execution]
D --> F[Settlement]
D --> G[Funding]
D --> H[Operational]
D --> I[Payout Partner]
E --> E1[QUOTE_EXPIRED]
E --> E2[QUOTE_EXECUTION_FAILED]
E --> E3[EXECUTION_FAILED_POST_DEBIT]
F --> F1[SETTLEMENT_FAILED]
F --> F2[TIMEOUT]
G --> G1[FUNDING_AMOUNT_MISMATCH]
G --> G2[MANUAL_REFUND]
H --> H1[LSP_OPERATIONAL_FAILURE]
I --> I1[PAYOUT_RETURNED]
I --> I2[LIMIT_EXCEEDED]
I --> I3[ACCOUNT_CANNOT_RECEIVE]
I --> I4[ACCOUNT_INVALID]
I --> I5[COMPLIANCE_REJECTED]
I --> I6[COUNTERPARTY_POST_TX_FAILED deprecated]
Comments Outside Diff (1)
-
mintlify/snippets/error-handling.mdx, line 373-390 (link)INVALID_BANK_ACCOUNTnot updated ingetUserFriendlyMessageexampleThe PR replaces
INVALID_BANK_ACCOUNTwithACCOUNT_INVALIDin the webhook FAILED example intransaction-lifecycle.mdx, but thegetUserFriendlyMessagecode sample still mapsINVALID_BANK_ACCOUNTand doesn't includeACCOUNT_INVALID(or the other new failure reasons likeCOMPLIANCE_REJECTED,ACCOUNT_CANNOT_RECEIVE, etc.). A developer copying this pattern to handle transactionfailureReasonvalues won't have a mapping for the newly documented reasons.Prompt To Fix With AI
This is a comment left during a code review. Path: mintlify/snippets/error-handling.mdx Line: 373-390 Comment: **`INVALID_BANK_ACCOUNT` not updated in `getUserFriendlyMessage` example** The PR replaces `INVALID_BANK_ACCOUNT` with `ACCOUNT_INVALID` in the webhook FAILED example in `transaction-lifecycle.mdx`, but the `getUserFriendlyMessage` code sample still maps `INVALID_BANK_ACCOUNT` and doesn't include `ACCOUNT_INVALID` (or the other new failure reasons like `COMPLIANCE_REJECTED`, `ACCOUNT_CANNOT_RECEIVE`, etc.). A developer copying this pattern to handle transaction `failureReason` values won't have a mapping for the newly documented reasons. How can I resolve this? If you propose a fix, please make it concise.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
mintlify/snippets/error-handling.mdx:373-390
**`INVALID_BANK_ACCOUNT` not updated in `getUserFriendlyMessage` example**
The PR replaces `INVALID_BANK_ACCOUNT` with `ACCOUNT_INVALID` in the webhook FAILED example in `transaction-lifecycle.mdx`, but the `getUserFriendlyMessage` code sample still maps `INVALID_BANK_ACCOUNT` and doesn't include `ACCOUNT_INVALID` (or the other new failure reasons like `COMPLIANCE_REJECTED`, `ACCOUNT_CANNOT_RECEIVE`, etc.). A developer copying this pattern to handle transaction `failureReason` values won't have a mapping for the newly documented reasons.
### Issue 2 of 2
mintlify/snippets/error-handling.mdx:143-158
**Deprecated values not mentioned in snippet**
`transaction-lifecycle.mdx` adds a note that `LIGHTNING_PAYMENT_FAILED` and `COUNTERPARTY_POST_TX_FAILED` may still be returned for historical transactions, but this snippet (which is the first error-handling reference many developers will read) has no equivalent callout. A developer whose integration receives a deprecated value for an older transaction will not find it in this list and may treat it as an unexpected/undocumented response.
Reviews (1): Last reviewed commit: "docs: sync outgoing payment failure reas..." | Re-trigger Greptile
| **Common outgoing failure reasons:** | ||
|
|
||
| - `QUOTE_EXPIRED` - Quote expired before execution | ||
| - `QUOTE_EXECUTION_FAILED` - Error executing the quote | ||
| - `QUOTE_EXECUTION_FAILED` - Error executing the quote; no funds were debited | ||
| - `EXECUTION_FAILED_POST_DEBIT` - Execution failed after debit; funds are refunded automatically | ||
| - `SETTLEMENT_FAILED` - The settlement leg failed | ||
| - `FUNDING_AMOUNT_MISMATCH` - Funding amount doesn't match expected amount | ||
| - `TIMEOUT` - Transaction didn't complete within its processing window | ||
| - `MANUAL_REFUND` - Transaction was refunded manually | ||
| - `LSP_OPERATIONAL_FAILURE` - Lightspark-internal operational issue; contact Lightspark | ||
| - `PAYOUT_RETURNED` - Receiving bank returned or reversed the payout | ||
| - `LIMIT_EXCEEDED` - Payout exceeds a partner limit | ||
| - `ACCOUNT_CANNOT_RECEIVE` - Recipient account can't accept the payment | ||
| - `ACCOUNT_INVALID` - Recipient account details are wrong or not found | ||
| - `COMPLIANCE_REJECTED` - Payout partner rejected on compliance grounds | ||
|
|
There was a problem hiding this comment.
Deprecated values not mentioned in snippet
transaction-lifecycle.mdx adds a note that LIGHTNING_PAYMENT_FAILED and COUNTERPARTY_POST_TX_FAILED may still be returned for historical transactions, but this snippet (which is the first error-handling reference many developers will read) has no equivalent callout. A developer whose integration receives a deprecated value for an older transaction will not find it in this list and may treat it as an unexpected/undocumented response.
Prompt To Fix With AI
This is a comment left during a code review.
Path: mintlify/snippets/error-handling.mdx
Line: 143-158
Comment:
**Deprecated values not mentioned in snippet**
`transaction-lifecycle.mdx` adds a note that `LIGHTNING_PAYMENT_FAILED` and `COUNTERPARTY_POST_TX_FAILED` may still be returned for historical transactions, but this snippet (which is the first error-handling reference many developers will read) has no equivalent callout. A developer whose integration receives a deprecated value for an older transaction will not find it in this list and may treat it as an unexpected/undocumented response.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Remove the negative guarantee from QUOTE_EXECUTION_FAILED across the enum description and docs. EXECUTION_FAILED_POST_DEBIT still carries the affirmative "debited then refunded automatically" wording. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Adds granular counterparty payout failure reasons to
OutgoingTransactionFailureReasonand syncs all documentation to match.New enum values, set at the partner boundary:
PAYOUT_RETURNED— receiving bank accepted then returned/reversed the payoutLIMIT_EXCEEDED— payout exceeds a recipient-, account-, or corridor-level limitACCOUNT_CANNOT_RECEIVE— account exists but can't accept the payment (dormant/frozen/restricted/unsupported currency)ACCOUNT_INVALID— recipient account not found or details wrongCOMPLIANCE_REJECTED— rejected on compliance grounds (sanctions/watchlist/KYC-AML)Also adds
EXECUTION_FAILED_POST_DEBITandLSP_OPERATIONAL_FAILURE, and marksLIGHTNING_PAYMENT_FAILEDandCOUNTERPARTY_POST_TX_FAILEDas deprecated (coarse fallback, retained for historical rows).Changes
OutgoingTransactionFailureReason.yaml+ bundle): full enum with per-value descriptions and deprecation notes.transaction-lifecycle.mdxand the list in theerror-handling.mdxsnippet to the enum — removed the non-existentINSUFFICIENT_BALANCE, addedTIMEOUT/MANUAL_REFUND/SETTLEMENT_FAILED, reordered to enum order, and fixed aFAILEDwebhook example to useACCOUNT_INVALID.Test plan
make build— bundles cleanly, no spec diff beyond the enum workmake lint-openapi— OpenAPI validates ✅🤖 Generated with Claude Code