Skip to content

feat(transactions): add railDetails to transaction source and destination - #1101

Open
akanter wants to merge 4 commits into
mainfrom
09-29-rail-transaction-leg
Open

akanter wants to merge 4 commits into
mainfrom
09-29-rail-transaction-leg

Conversation

@akanter

@akanter akanter commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds railDetails to transaction sources and destinations. It is a oneOf over per-rail schemas, discriminated by paymentRail. Each bank rail has its own status values, bank account fields and identifiers. The schemas carry only fields that will be populated.

paymentRail Schema status values Rail-specific fields
ONCHAIN OnChainRailDetails — transactionHash, network
ACH, ACH_SAME_DAY AchRailDetails PENDING, SETTLED, RETURNED, REVERSED, FAILED bankAccount, traceNumber, addenda, settledAt, returnedAt, reversedAt
WIRE WireRailDetails PENDING, SETTLED, FAILED bankAccount, imad, originatorToBeneficiaryInformation, settledAt
FEDNOW FedNowRailDetails PENDING, SETTLED, FAILED bankAccount, endToEndId, remittanceInformation, settledAt
RTP RtpRailDetails PENDING, SETTLED, FAILED bankAccount, endToEndId, remittanceInformation, settledAt

The four US bank rails compose BaseUsdBankRailDetails, which holds the shared bankAccount (UsdBankAccountDetails: accountHolderName, routingNumber, masked accountNumber) and settledAt. Wires use WireBankAccountDetails, which adds bankName.

railDetails is on AccountTransactionSource, AccountTransactionDestination and RealtimeFundingTransactionSource. UMA-address sides don't get one.

Top-level status

A transaction's status reports the payment, and railDetails.status reports the transfer on its rail. Webhook events are unchanged.

  • Returned payout: keeps the published lifecycle, COMPLETED → FAILED (PAYOUT_RETURNED) → REFUND_PENDING → REFUND_COMPLETED. The FAILED event's destination railDetails now also shows RETURNED with returnedAt.
  • Returned incoming payment: stays COMPLETED. Its webhook is sent again for the current status, with the source's railDetails showing RETURNED.

TransactionStatus.REFUNDED is marked deprecated in its description, because a refund is reported on the refund object.

Deprecations (still populated)

  • onChainTransaction on all three sides. Its OnChainTransaction schema is unchanged. The ONCHAIN variant is a separate OnChainRailDetails that requires paymentRail, so the discriminator is required on every variant and oasdiff reports no breaking changes.
  • Flat originator fields on RealtimeFundingTransactionSource: accountHolderName, accountIdentifier, bankName, bankIdentifier, paymentRail, remittanceInformation, endToEndId, traceNumber.

Open for review

  • Returns are ACH-only for now: wire, FedNow and RTP have no RETURNED status, and there is no return reason code yet. Adding either later is an additive change.
  • Rails outside the oneOf (SEPA, SWIFT, PIX, …) have no railDetails. Their deprecated flat originator fields stay populated and are documented as the only source for those rails. A return on those rails has no per-side status until a variant exists.
  • Discriminator values: paymentRail reuses PaymentRail values and adds ONCHAIN, which is only valid inside railDetails.
  • Not deprecated yet: OutgoingTransaction.paymentRail, which mirrors the destination leg's rail.

Docs

  • Webhook examples: on-chain in/out, incoming wire, and a returned ACH payout (OUTGOING_PAYMENT.FAILED with PAYOUT_RETURNED and destination railDetails RETURNED).
  • Webhook descriptions: the incoming webhook also fires when the source's railDetails.status changes under an unchanged status, repeating the event type.
  • Lifecycle page: explains the rail status beside the transaction status, and the bank-return scenario's FAILED step carries railDetails RETURNED.
  • Changelog entry, plus reconciliation and receipts snippets pointing at railDetails.

Preview

Test plan

  • make build: bundles regenerated, and openapi.yaml is identical to mintlify/openapi.yaml.
  • make lint-openapi: 0 errors.
  • oasdiff breaking against the merge base with main: no breaking changes.
  • Automated pre-PR review: fixed the lifecycle handler examples and the reconciliation guide's return guidance it flagged, and restored ACH addenda after it noted ACH remittance had no replacement field. The unsupported-rail return gap is listed under open questions.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

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

3 Skipped Deployments
Project Deployment Actions Updated
grid-cards-demo Ignored Ignored Preview Oct 2, 2026 4:20pm UTC
grid-flow-builder Ignored Ignored Preview Oct 2, 2026 4:20pm UTC
grid-wallet-demo Ignored Ignored Preview Oct 2, 2026 4:20pm UTC

Request Review

Copy link
Copy Markdown

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

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Critical risk] Restructures the public API contract for transaction rails.

The PR appears safe to merge based on the reviewed changes.

Summary

The PR adds per-rail transaction-leg details and updates webhook and reconciliation guidance.

  • Shared US bank-account schemas now compose the ACH, wire, FedNow, and RTP variants.
  • The documentation distinguishes a completed transaction from a later ACH return on its destination leg.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Transaction --> Source
  Transaction --> Destination
  Source --> RailDetails
  Destination --> RailDetails
  RailDetails --> OnChain
  RailDetails --> ACH
  RailDetails --> Wire
  RailDetails --> FedNow
  RailDetails --> RTP
Loading

Reviews (3) · Last reviewed commit: "refactor(transactions): keep bankName on..."

Comment thread openapi/components/schemas/transactions/RealtimeFundingTransactionSource.yaml Outdated
Comment thread openapi/webhooks/outgoing-payment.yaml Outdated
Comment thread openapi/components/schemas/transactions/TransactionStatus.yaml Outdated
Comment thread mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx Outdated
@ls-bolt

ls-bolt Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

⚡ Review rounds — updated in place, latest first.

Round 1 · f1830f9

  • Deprecated flat originator fields on the external funding source are documented as still populated, and as the only source on rails without a railDetails variant, such as SWIFT (Greptile)
  • Incoming and outgoing webhook descriptions cover a railDetails.status change under an unchanged status: the event type repeats, so dedupe on id (Greptile)
  • COMPLETED descriptions and the changelog scope the return and reversal behavior to ACH (Greptile)
  • Returned-funds crediting is left open as a product question on the thread
  • Verified: make build, make lint-openapi (2 warnings, 0 errors), mint openapi-check, and oasdiff against the merge base show no breaking changes. Automated pre-push review skipped: docs and spec wording only

@mintlify

mintlify Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

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

Project Status Preview Updated
Grid 🟢 Ready View Preview Oct 2, 2026, 4:22 PM

@ls-bolt

ls-bolt Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

⚡ Review ledger

Round 1

  1. Migration loses uncovered rail details → FIXED: flat fields in RealtimeFundingTransactionSource.yaml and the changelog name the SWIFT fallback
  2. Webhook trigger description conflicts → FIXED: outgoing-payment.yaml and incoming-payment.yaml descriptions
  3. Return promise exceeds rail schemas → FIXED: TransactionStatus.yaml, OutgoingTransactionStatus.yaml, changelog
  4. Returned funds path is missing → DEFERRED: product decision on where returned funds are credited, asked on the thread

Round 2

  1. Returned-funds path missing from the Bank Return example → NOT APPLICABLE: per @akanter, where a return lands depends on debit/credit and originating/receiving direction, so the doc deliberately promises no destination; it already says status stays COMPLETED and the return is read from railDetails.

Round 3

  1. Bank-account fields on the source should be deprecated (@pengying) → NOT APPLICABLE: AccountTransactionSource has no flat bank fields. The ones on RealtimeFundingTransactionSource are already deprecated in favor of railDetails. Asked whether a different field was meant.

Round 4

  1. Is bankName present for FedNow, ACH and RTP? (@akanter) → FIXED: c241e95. Only wires carry it, so it moved to WireBankAccountDetails.
  2. Drop bankName from non-wire rails if we won't populate it (@akanter) → FIXED: c241e95
  3. Returned payout should go FAILED with railDetails.status: RETURNED (@akanter) → PENDING: asked whether incoming payments follow the same rule before rewriting the lifecycle docs

Round 5

  1. A returned payout's status is FAILED, the known status at the destination (@shreyav) → FIXED: 02e56e7 restores the published payout lifecycle, with railDetails RETURNED on the FAILED event
  2. Changing returned-payout events breaks integrators (@shreyav) → FIXED: 02e56e7. Payout events are unchanged; COMPLETED → FAILED → REFUND_* as published
  3. Returned payout goes FAILED plus railDetails RETURNED (@akanter) → FIXED: 02e56e7. A returned incoming payment stays COMPLETED and re-sends its current event with RETURNED

…tion

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ls-bolt
ls-bolt Bot force-pushed the 09-29-rail-transaction-leg branch from f1830f9 to 2963459 Compare September 30, 2026 19:18
@akanter
akanter marked this pull request as ready for review September 30, 2026 19:42
@akanter
akanter requested review from pengying and shreyav September 30, 2026 19:42
Comment thread mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx Outdated
@ls-bolt

ls-bolt Bot commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

🦣 Congratulations @shreyav - your substantive review earned a Giant bone-crushing dog! (uncommon)

Epicyon was the largest known canid and had a short, powerful skull.

View your Frost-dex: https://zeus.dev.dev.sparkinfra.net/#/dinodex/shreyav?section=ice-age

Comment thread mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx Outdated
Comment thread openapi/components/schemas/transactions/AchRailDetails.yaml
AchRailDetails, WireRailDetails, RtpRailDetails and FedNowRailDetails now compose
BaseUsdBankRailDetails, which carries bankAccount (UsdBankAccountDetails) and
settledAt. Each rail keeps its own paymentRail, status and rail identifiers.
bankAccount.bankName is optional on every US rail and is populated on wires.

Co-Authored-By: shreyav <shreyav@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -14,9 +14,12 @@ allOf:
type: string

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.

[Re: line +3]

I think there are some fields in here about the bank account details that need to be marked deprecated?

See this comment inline on Graphite.

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.

AccountTransactionSource has no bank-account fields of its own: accountId points at the account, and onChainTransaction is deprecated in this PR. The flat bank fields live on RealtimeFundingTransactionSource (accountHolderName, accountIdentifier, bankName, bankIdentifier, paymentRail, remittanceInformation, endToEndId, traceNumber), and all of them are already marked deprecated there in favor of railDetails. Did you have a different field in mind?


🤖 shimmering-witness-10(#10) | Feedback

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.

ping @pengying

@ls-bolt

ls-bolt Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

📌 Bolt Status

2026-10-01 07:31:16 UTC — ⚡ Agent shimmering-witness-10(#10) started
2026-10-02 16:15:00 UTC — ⚡ Agent shimmering-witness-12(#12) started


Feedback

@ls-bolt

ls-bolt Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

🦣 Congratulations @pengying - your substantive review earned a Giant rat-kangaroo! (common)

A powerful jaw and varied teeth suggest this large musky-rat-kangaroo relative was omnivorous.

View your Frost-dex: https://zeus.dev.dev.sparkinfra.net/#/dinodex/pengying?section=ice-age

Comment thread openapi/components/schemas/transactions/UsdBankAccountDetails.yaml Outdated
@@ -14,9 +14,12 @@ allOf:
type: string

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.

ping @pengying

Comment thread openapi/components/schemas/transactions/AchRailDetails.yaml
Comment thread mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx Outdated
Comment thread mintlify/platform-overview/core-concepts/transaction-lifecycle.mdx Outdated
ACH, RTP and FedNow entries carry no bank name, so UsdBankAccountDetails drops
it. WireRailDetails uses WireBankAccountDetails, which adds bankName.

Co-Authored-By: akanter <akanter@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ls-bolt

ls-bolt Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@greptile review

… beside it

A returned payout keeps its published lifecycle: COMPLETED, then FAILED with
PAYOUT_RETURNED, then REFUND_PENDING and REFUND_COMPLETED. Its destination's
railDetails now also reports RETURNED with returnedAt. A returned incoming
payment stays COMPLETED, and its webhook is sent again with the source's
railDetails showing RETURNED.

Restores the published payout status, failure-reason and lifecycle text, and
turns the returned-payout webhook example into OUTGOING_PAYMENT.FAILED.

Co-Authored-By: shreyav <shreyav@users.noreply.github.com>
Co-Authored-By: akanter <akanter@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
staging - mintlify — 02e56e7e Deployed Oct 2, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants