Skip to content

docs: make /quotes the single transfer path, deprecate /transfer-in and /transfer-out - #856

Merged
shreyav merged 9 commits into
mainfrom
claude/transfer-api-deprecation-docs-6ycamq
Aug 24, 2026
Merged

docs: make /quotes the single transfer path, deprecate /transfer-in and /transfer-out#856
shreyav merged 9 commits into
mainfrom
claude/transfer-api-deprecation-docs-6ycamq

Conversation

@shreyav

@shreyavshreyav commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Same-currency transfers now route through the quote endpoint on the backend. This makes POST /quotes the single documented path for moving money, deprecates the platform transfer endpoints, and removes the unbuilt agent ones.

Note

This PR will pick up the breaking-change label — see Breaking changes below. That is expected and comes from removing the agent transfer endpoints.

Why

In sparkcore, both platform transfer handlers now build a QuoteRequest and delegate to gen_run_create_quote:

  • sparkcore/grid/api_handlers/transfer_out.py:317 (_gen_transfer_out_via_quotes)
  • sparkcore/grid/api_handlers/transfer_in.py:327 (_gen_transfer_in_via_quotes)

Both map amount onto lockedCurrencySide: SENDING / lockedCurrencyAmount and set immediatelyExecute: true. That mapping is what the migration notes here document.

Two things this deliberately does not claim about the platform endpoints:

  • The delegation is gated per-platform (GRID_TRANSFER_IN_VIA_QUOTES / GRID_TRANSFER_OUT_VIA_QUOTES), and they still return a Transaction with unchanged request/response shapes. Those are deprecated, not removed.
  • No sunset date is stated, since none has been set.

API reference

  • deprecated: true on POST /transfer-in and POST /transfer-out, each with a field-by-field migration to POST /quotes. This renders a badge in Mintlify and propagates to the generated SDKs via Stainless — no .stainless/stainless.yml change needed for these, and removing the resources there would break the SDKs.
  • Inverted the guidance on POST /quotes, which previously read "If you are transferring funds in the same currency, use the /transfer-in or /transfer-out endpoints instead."
  • Added a sameCurrencyAccountToAccount request example, and updated the Same-Currency / Cross-Currency tag descriptions.

Removed: agent transfer APIs

POST /agents/me/transfer-in and POST /agents/me/transfer-out are removed outright rather than deprecated. There is no handler for either in sparkcore, so nothing can be using them, and agent transfers will go through quotes when they are built.

Removing the endpoints orphaned the rest of the transfer-shaped agent model, so that goes too:

RemovedWhy it was orphaned
AgentActionType.TRANSFER_OUT / TRANSFER_INNo endpoint could produce an action of either type
AgentTransferDetails + AgentAction.transferDetailsOnly ever populated for those action types
AgentPermission.CREATE_TRANSFERSGated only these two endpoints; CREATE_QUOTES / EXECUTE_QUOTES cover the quote path

.stainless/stainless.yml and the agent guides (policies-and-permissions.mdx, approvals-and-audit.mdx) follow.

Worth a reviewer's eye: removing the enum values and the permission goes a step beyond removing the two endpoints. It is the coherent end state if agent transfers become quotes, but it is the most opinionated part of this PR and the easiest piece to scale back.

Guides

Every transfer-in/transfer-out example is now the equivalent POST /quotes call with immediatelyExecute: true. The non-obvious part: a quote response is not a transaction, so response payloads and the "track status" steps read transactionId off the quote.

send-payment.mdx: 511 lines to 369. It had two parallel ~140-line walkthroughs, same-currency and cross-currency, that both called POST /quotes — a split dating from when same-currency was a genuinely different API. They are now one Send a payment flow whose real fork is one-step (immediatelyExecute) versus two-step (review the rate, then execute). That is the choice that actually exists, and it is not the same question as whether the currencies differ.

That merge also resolved two Transaction statuses tables that described the same statuses differently — now one reconciled table. The two-card Overview grid framing "two payment methods" is gone.

One deprecation notice, not four. A first pass repeated the same "use /quotes instead" note on four pages, so a reader going through core concepts and then a payment guide hit it three times. It now appears once, on the quote system page, where the "when do I need a quote?" question is answered. The API reference badges and the changelog carry the announcement for anyone arriving from the old endpoints.

The transaction lifecycle page's Same-Currency Transfers section shrank from ~50 lines to a paragraph, for the same reason: its two request blocks re-showed the lifecycle walked through immediately above them.

Validation

CheckResult
make lint (lint.yml)exit 0 — 0 errors; 663 problems, unchanged from baseline (all pre-existing)
make build + bundle sync (openapi-build.yml)openapi.yaml / mintlify/openapi.yaml in sync, rebuild is deterministic
oasdiff 1.16.0 (openapi-breaking-changes.yml)6 errors / 7 warnings — see below
Doc anchorsall verified, including relinking the two inbound #same-currency-transfers links to #send-a-payment

mint broken-links requires a TTY so it could not be run here; it is not a CI gate.

Breaking changes

oasdiff reports 6 errors, all from the agent removals:

  • POST /agents/me/transfer-in and POST /agents/me/transfer-out — path removed without deprecation
  • CREATE_TRANSFERS enum value removed from POST /agents and PATCH /agents/{agentId}/policy
  • TRANSFER_IN / TRANSFER_OUT enum values removed from the agent-action webhook

Plus 7 warnings for transferDetails disappearing from agent action responses.

The workflow does not fail the job on findings — it posts a sticky comment, adds the breaking-change label, and notes that an API reviewer must approve. Since none of these endpoints or fields have a backend implementation, the breakage is theoretical, but the label is correct and the gate should be honored.

Follow-up: grid-visualizer code generator

components/grid-visualizer/src/lib/code-generator.ts still generates /transfer-out (L190) and /transfer-in (L215) sample code — canUseTransferOut / canUseTransferIn short-circuit ahead of the quote path at L107-111.

This PR leaves that code alone and only marks the two endpoints Deprecated in components/grid-visualizer/CLAUDE.md, so the doc stays accurate to what the tool emits today. Routing those branches through the quote path is a behavior change to the visualizer with its own testing surface, and belongs in a separate PR.

@mintlify

mintlifyBot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

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

ProjectStatusPreviewUpdated (UTC)
Grid🟢 ReadyView PreviewAug 23, 2026, 11:49 PM

@vercel

vercelBot commented Aug 23, 2026

Copy link
Copy Markdown

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

2 Skipped Deployments
ProjectDeploymentActionsUpdated (UTC)
grid-flow-builderIgnoredIgnoredPreviewAug 24, 2026 8:50pm
grid-wallet-demoIgnoredIgnoredPreviewAug 24, 2026 8:50pm

Request Review

@github-actions

github-actionsBot commented Aug 23, 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 quote create, deprecate transferin/transferout

go

docs(api): deprecate transfer-in/out endpoints, update quote descriptions

kotlin

chore(api): deprecate transfer-in/transfer-out endpoints in favor of quotes

openapi

chore(api): deprecate transfer-in/transfer-out endpoints in favor of quotes

php

docs(api): deprecate transfer-in/out endpoints, update quotes to support same-currency

python

fix(api): deprecate transfer_in and transfer_out methods

ruby

docs(api): deprecate transfer_in/transfer_out, update quotes/receiver/crypto descriptions

typescript

docs(api): deprecate transfer-in/transfer-out in favor of quotes endpoint
⚠️grid-openapistudio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️

⚠️grid-rubystudio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️build ✅lint ✅test ✅

⚠️grid-gostudio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ⚠️build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@959e980695b38092d296ce77693b3a45534cea7c
⚠️grid-kotlinstudio · code

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ⚠️build ✅lint ✅test ❗

⚠️grid-typescriptstudio · conflict

Your SDK build had at least one warning diagnostic.

⚠️grid-pythonstudio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ⚠️build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/5db55543d9a8e4695b15280a2566323bf50aebd0/grid-0.0.1-py3-none-any.whl
⚠️grid-phpstudio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️lint ✅test ✅

⚠️grid-clistudio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
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-08-24 21:44:32 UTC

@github-actions

github-actionsBot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

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

Errors (6)

  • POST /agents — removed the enum value CREATE_TRANSFERS of the request property policy/permissions/items/ [request-property-enum-value-removed].
  • POST /agents/me/transfer-in — api path removed without deprecation [api-path-removed-without-deprecation].
  • POST /agents/me/transfer-out — api path removed without deprecation [api-path-removed-without-deprecation].
  • PATCH /agents/{agentId}/policy — removed the enum value CREATE_TRANSFERS of the request property permissions/items/ [request-property-enum-value-removed].
  • POST webhook:agent-action — removed the enum value TRANSFER_IN of the request property allOf[subschema #2]/data/type [request-property-enum-value-removed].
  • POST webhook:agent-action — removed the enum value TRANSFER_OUT of the request property allOf[subschema #2]/data/type [request-property-enum-value-removed].

Warnings (7)

Show sample
  • GET /agents/approvals — removed the optional property data/items/transferDetails from the response with the 200 status [response-optional-property-removed].
  • GET /agents/me/actions — removed the optional property data/items/transferDetails from the response with the 200 status [response-optional-property-removed].
  • GET /agents/me/actions/{actionId} — removed the optional property transferDetails from the response with the 200 status [response-optional-property-removed].
  • POST /agents/me/quotes/{quoteId}/execute — removed the optional property transferDetails from the response with the 200 status [response-optional-property-removed].
  • POST /agents/{agentId}/actions/{actionId}/approve — removed the optional property transferDetails from the response with the 200 status [response-optional-property-removed].
  • POST /agents/{agentId}/actions/{actionId}/reject — removed the optional property transferDetails from the response with the 200 status [response-optional-property-removed].
  • POST webhook:agent-action — removed the request property allOf[subschema #2]/data/transferDetails [request-property-removed].

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

@shreyavshreyav changed the title docs: deprecate /transfer-in and /transfer-out in favor of /quotesdocs: make /quotes the single transfer path, deprecate /transfer-in and /transfer-outAug 24, 2026
@shreyav
shreyavforce-pushed the claude/transfer-api-deprecation-docs-6ycamq branch from 5fa9d79 to 5e4868dCompareAugust 24, 2026 04:09
@shreyav
shreyav changed the base branch from main to claude/incoming-processing-webhookAugust 24, 2026 04:10
@shreyav
shreyav marked this pull request as ready for review August 24, 2026 15:31
@greptile-apps

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes quotes the documented path for same- and cross-currency transfers, deprecates the platform transfer endpoints, and removes the unimplemented agent transfer contract. It also updates generated OpenAPI/Stainless artifacts and consolidates payment guides, but the rewritten execution walkthrough omits the required SCA continuation.

  • Adds same-currency quote examples and field-by-field migration guidance.
  • Deprecates /transfer-in and /transfer-out.
  • Removes agent transfer paths, permissions, action variants, and transfer details.
  • Reworks payment guides around one-step and two-step quote execution.

Confidence Score: 4/5

The PR should not merge until the payment walkthrough handles the SCA branch that can leave an executed quote awaiting authorization.

The rewritten guide tells integrations that quote execution always begins transaction processing, while the changed flow reaches an existing endpoint contract that can instead require a follow-up authorization before any transfer starts.

Files Needing Attention: mintlify/payouts-and-b2b/payment-flow/send-payment.mdx

Important Files Changed

FilenameOverview
openapi/paths/quotes/quotes.yamlExpands quote creation documentation and examples to cover same-currency transfers.
openapi/paths/transfers/transfer_in.yamlDeprecates transfer-in and documents its request and response migration to quotes.
openapi/paths/transfers/transfer_out.yamlDeprecates transfer-out and documents its request and response migration to quotes.
openapi/components/schemas/agents/AgentAction.yamlRemoves transfer-specific action details as part of the acknowledged agent API break.
openapi/components/schemas/agents/AgentActionType.yamlRemoves the acknowledged transfer-in and transfer-out action variants.
openapi/components/schemas/agents/AgentPermission.yamlRemoves the acknowledged agent transfer permission.
mintlify/payouts-and-b2b/payment-flow/send-payment.mdxConsolidates payment walkthroughs around quotes but incorrectly presents execute as always advancing to processing, omitting SCA.
mintlify/platform-overview/core-concepts/quote-system.mdxReframes quotes as the unified transfer mechanism and retains separate SCA guidance.
.stainless/stainless.ymlRemoves SDK resource mappings corresponding to the removed agent transfer contract.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Create quote] --> B{Immediately execute?}
B -->|No| C[Review quote]
C --> D[Execute quote]
B -->|Yes| E{SCA required?}
D --> E
E -->|No| F[Transaction processing]
E -->|Yes| G[PENDING_AUTHORIZATION]
G --> H[Authorize quote challenge]
H --> F
F --> I[Track transaction]
Loading
Prompt To Fix All With AI
### Issue 1
mintlify/payouts-and-b2b/payment-flow/send-payment.mdx:182-183
**SCA blocks transaction processing**
When SCA applies, `POST /quotes/{quoteId}/execute` returns `PENDING_AUTHORIZATION` without initiating the transfer, but this step says the quote always advances to `PROCESSING`, causing integrations to monitor a transaction that remains blocked instead of authorizing the quote.
```suggestionWhen SCA is not required, the quote comes back with `status` `PROCESSING` and the same`transactionId` it carried at creation. When SCA is required, it instead returns with`PENDING_AUTHORIZATION`; authorize the quote's `scaChallenge` with`POST /quotes/{quoteId}/authorize` to release the transfer.```---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "docs: trim the send-payment intro and st..." | Re-trigger Greptile

Comment on lines +182 to +183
The quote comes back with `status` `PROCESSING` and the same `transactionId` it carried at
creation.

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.

P1SCA blocks transaction processing

When SCA applies, POST /quotes/{quoteId}/execute returns PENDING_AUTHORIZATION without initiating the transfer, but this step says the quote always advances to PROCESSING, causing integrations to monitor a transaction that remains blocked instead of authorizing the quote.

Suggested change
The quote comes back with `status``PROCESSING` and the same `transactionId` it carried at
creation.
When SCA is not required, the quote comes back with `status``PROCESSING` and the same
`transactionId` it carried at creation. When SCA is required, it instead returns with
`PENDING_AUTHORIZATION`; authorize the quote's `scaChallenge` with
`POST /quotes/{quoteId}/authorize` to release the transfer.

Knowledge Base Used:Payments, quotes, and transfers API

Prompt To Fix With AI
This is a comment left during a code review.
Path: mintlify/payouts-and-b2b/payment-flow/send-payment.mdx
Line: 182-183
Comment:
**SCA blocks transaction processing**
When SCA applies, `POST /quotes/{quoteId}/execute` returns `PENDING_AUTHORIZATION` without initiating the transfer, but this step says the quote always advances to `PROCESSING`, causing integrations to monitor a transaction that remains blocked instead of authorizing the quote.
```suggestionWhen SCA is not required, the quote comes back with `status` `PROCESSING` and the same`transactionId` it carried at creation. When SCA is required, it instead returns with`PENDING_AUTHORIZATION`; authorize the quote's `scaChallenge` with`POST /quotes/{quoteId}/authorize` to release the transfer.```**Knowledge Base Used:**[Payments, quotes, and transfers API](https://app.greptile.com/lightspark/-/custom-context/knowledge-base/lightsparkdev/grid-api/-/docs/payments-and-quotes-api.md)---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Base automatically changed from claude/incoming-processing-webhook to mainAugust 24, 2026 15:42
shreyav added a commit that referenced this pull request Aug 24, 2026
…858)
> [!NOTE]
> **Bottom of a three-PR stack**, based on `main` and mergeable on its
own. #856 and #857 sit on top of it. Deliberately isolated so the
sparkcore fix that depends on this enum isn't blocked behind the docs
work above.
## The bug
`WebhookType` describes itself as dot-notation that *"lets consumers
route purely on type without inspecting `data.status`"*.
The incoming family breaks that promise. `_get_incoming_webhook_type`
(`sparkcore/grid/webhooks/webhook_handler.py:142`) collapses four states
onto one event:
```python
case (CREATED | PENDING | PROCESSING | SENT):
return WebhookType.INCOMING_PAYMENT_DOT_PENDING
```
The outgoing twin 24 lines above maps `PROCESSING` to its own event. So
a pull into an internal account fires `INCOMING_PAYMENT.PENDING`
**twice**, and the second payload carries `"status": "PROCESSING"`
inside an envelope typed `PENDING` — exactly the inspect-`data.status`
case the contract says consumers should not need.
Likely why it went unnoticed: the receive-operation path (ordinary
deposits) does not appear to reach `PROCESSING`/`SENT`, so the collapse
was harmless. `GK.GRID_INCOMING_TRANSACTION_REFACTOR` then routed send
operations — which *do* pass through those states — into this function
without extending it.
## This PR
Contract only. Adds `INCOMING_PAYMENT.PROCESSING` to `WebhookType` and
to the `IncomingPaymentWebhook` `type` enum, mirroring the outgoing
family.
**sparkcore does not emit the event yet.** Its `WebhookType` is
generated from this spec, so this has to land before the emission fix
can reference the new member.
## Follow-up in webdev, after this merges
1. Regenerate the grid-api Python SDK so
`WebhookType.INCOMING_PAYMENT_DOT_PROCESSING` exists.
2. Split `PROCESSING | SENT` out of the `PENDING` case in
`_get_incoming_webhook_type`. `SENT` belongs with `PROCESSING`, not
`PENDING` — `gen_convert_send_op_to_incoming_transaction` already maps
`SENT` onto status `PROCESSING` (`transaction.py:891`), so that is what
makes the envelope agree with its payload.
Note for whoever picks that up: it changes behavior for existing
integrators, who currently receive two `PENDING` events and will start
receiving `PENDING` then `PROCESSING`.
A smaller instance of the same collapse is out of scope here:
`_get_incoming_webhook_type` also folds `EXPIRED` into
`INCOMING_PAYMENT.FAILED`.
## Validation
| Check | Result |
|---|---|
| `make lint` | exit 0 — 0 errors |
| `make build` + bundle sync | `openapi.yaml` / `mintlify/openapi.yaml`
in sync |
| oasdiff 1.16.0 vs `main` | no breaking changes — adding an enum value
widens the contract |
---
_Generated by [Claude
Code](https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv)_
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
shreyavand others added 6 commits August 24, 2026 08:42
Same-currency transfers now route through the quote endpoint on the
backend, so the docs should point integrators there.
API reference:
- Mark POST /transfer-in and POST /transfer-out `deprecated: true` and
document the field-by-field migration to POST /quotes in each
description.
- Invert the note on POST /quotes that sent same-currency traffic to the
transfer endpoints, and add a same-currency request example.
- Update the Same-Currency/Cross-Currency tag descriptions to match.
Guides: replace every transfer-in/transfer-out example with the
equivalent POST /quotes call using `immediatelyExecute: true`, and update
the surrounding prose and response payloads (a quote carries
`transactionId` rather than being a transaction itself).
Also mark the endpoints deprecated in the repo's agent-facing reference
docs so tooling stops recommending them, and add a changelog entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
The first pass repeated the same "use /quotes instead" note on four
pages, so a reader working through core concepts and then a payment
guide hit it three times.
Keep one canonical note on the quote system page, which is where the
"when do I need a quote?" question is actually answered. Drop it from
the two task guides — someone following those just needs the correct
call — and from the transaction lifecycle page.
Also collapse the lifecycle page's Same-Currency Transfers section. It
existed because same-currency used to be a genuinely different API path;
now that it is an ordinary quote, the two request blocks just re-showed
the lifecycle walked through immediately above them. Replaced with a
short paragraph and a link to the worked example.
The API reference deprecation badges and the changelog entry carry the
announcement for anyone arriving from the old endpoints.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
Two structural cleanups now that quotes are the single path.
send-payment.mdx had two parallel ~140-line walkthroughs, one for
same-currency and one for cross-currency, that both called POST /quotes.
The split dated from when same-currency was a genuinely different API.
Merged them into one "Send a payment" flow whose real fork is one-step
(`immediatelyExecute`) versus two-step (review the rate, then execute) —
which is the choice that actually exists, and is not the same question as
whether the currencies differ.
That also resolved two "Transaction statuses" tables which described the
same statuses differently; they are now one reconciled table. The
two-card Overview grid framing "two payment methods" is gone. 511 lines
down to 369.
Removed /agents/me/transfer-in and /agents/me/transfer-out outright
rather than deprecating them: there is no handler for either in
sparkcore, so nothing can be using them, and agent transfers will go
through quotes when they are built.
Removing the endpoints orphaned the rest of the transfer-shaped agent
model, so that goes too: the TRANSFER_OUT and TRANSFER_IN action types
(nothing could produce them), AgentTransferDetails and
AgentAction.transferDetails, and the CREATE_TRANSFERS permission, which
gated only these two endpoints — CREATE_QUOTES and EXECUTE_QUOTES cover
the quote-based path. Stainless config and the agent guides follow.
oasdiff reports 6 errors and 7 warnings for the removals, so this PR
picks up the breaking-change label and needs API-reviewer sign-off. The
workflow does not fail on findings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
…out stub
Review feedback:
Pick between one-step and two-step execution on whether your UX shows the
customer rates or fees, not on whether the currencies match. A
same-currency transfer has no exchange rate but can still carry fees
worth surfacing, so the two-step flow is a reasonable choice there too.
Restore the original "Monitor completion" wording on the last step.
Scope the page description to what the page covers. It is not limited to
internal-to-external, so say any combination of internal and external
accounts in either direction. UMA destinations use the same endpoint but
this page carries no UMA example, so link out to the global-p2p guide
rather than implying coverage.
Drop the sandbox "Transferring out funds" section. Once it stopped
naming /transfer-out it was one sentence pointing at the transfer-in
patterns, so fold that into the patterns note, which now says the
suffixes govern the external account in either direction. The
"## Transfer in" heading stays so the existing #transfer-in link keeps
resolving.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
…ome patterns
The sandbox pages framed their content around transfer-in and
transfer-out, which stopped being API concepts.
On the API reference sandbox page, the "Transfer in" section opened by
re-explaining how internal accounts get funded in production. Internal
Accounts already covers that — the list endpoints, the funding payment
instructions, and how to display them to a customer — so link there
instead. What is genuinely sandbox-only is the fund endpoint, which is
now the body of a "Funding an internal account" section, plus a line on
using a quote to exercise the pull path.
Moved the suffix table up under "Adding external accounts", next to the
sentence that already tells you the last 3 digits pick the scenario. The
suffix is a property of the account, not of a direction of travel.
The payouts sandbox page had the same split: two POST /quotes blocks
differing only in which side held the external account, with the suffix
table between them. Now one "Testing Transfer Outcomes" section with the
table first and a single example, noting you swap the two accountId
values to test the other direction.
Repointed the one inbound #transfer-in link.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
Review feedback. Shorten the page description to "Learn how to send
payments between accounts", drop "any combination of" and "in either
direction" from the intro sentence, and cut the "like bank returns"
example from the pointer to the transaction lifecycle guide.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
@shreyav
shreyav requested a review from pengyingAugust 24, 2026 17:06

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.

@k15z heads up we're deprecating the transfer api in favor of unifying everything into quotes

@@ -74,46 +74,14 @@ Most transactions on Grid are completed in seconds.

## Same-Currency Transfers

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.

do we need to break out same currency transfers or can we delete the section?

@ls-bolt

ls-boltBot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

🦣 Congratulations @pengying - your substantive review earned a Neolicaphrium! (common)

A small litoptern, it survived far later than most members of its ancient lineage.

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

## Same-Currency Transfers

Use the `/transfer-out` endpoint when sending funds in the same currency (no exchange rate needed). This is the simplest and fastest option for domestic transfers.
Use the `/quotes` endpoint when sending funds in the same currency (no exchange rate needed). Quotes cover same-currency and cross-currency transfers alike, so one integration handles both.

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.

i don't know if we still need the distinction for same currency now

…e section
Review feedback.
The execute step claimed the quote always comes back PROCESSING. Where SCA
applies it does not: the endpoint's own 200 description says the transfer
is not initiated, the quote returns PENDING_AUTHORIZATION with an
scaChallenge, and re-calling execute returns 409. An integration following
the old text would have polled a transaction that never moves. Added the
branch and the authorize call.
Deleted the Same-Currency Transfers section from the transaction lifecycle
page. It said same-currency follows the lifecycle above unchanged, which is
the argument for not having a section. Its one concrete detail, the
pullable external account requirement, is covered on the account model and
quote system pages among others. Nothing links to the removed anchor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
The warning restated what quote-system.mdx already covers under Strong
Customer Authentication, down to the 409 on re-calling execute.
Kept the correction it carried — execute does not always come back
PROCESSING — as one clause with a link, rather than a second copy of the
mechanics.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
Review feedback from @pengying: the same-currency distinction no longer
earns its own section now that both go through POST /quotes.
Deleting the snippet outright would have lost content, though.
cross-currency.mdx covered none of immediatelyExecute, paymentRail or
remittanceInformation, and remittanceInformation appears nowhere else in
global-p2p — so a reader there would have lost the 80-character reference
that rides along on ACH Addenda, FedNow/RTP, and wire OBI. Merged instead.
cross-currency.mdx becomes accounts.mdx, covering any payment to an
internal or external account with or without conversion. Its fork is
one-step versus two-step execution, matching send-payment.mdx. Folded in
the three fields above, and noted on the review step that
immediatelyExecute skips it.
Split "Funding with cryptocurrencies" into crypto-funding.mdx. It is about
how a quote is funded rather than where it is sent, and it was the largest
thing in the file.
The global-p2p page dropped from three methods to two: to an account, or
to an UMA address. Nothing linked to the retired anchors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TxsyZEDjQDt97rR3kd2kxv
@shreyav
shreyav merged commit 07cf582 into mainAug 24, 2026
11 checks passed
@shreyav
shreyav deleted the claude/transfer-api-deprecation-docs-6ycamq branch August 24, 2026 21:38
shreyav added a commit that referenced this pull request Aug 24, 2026
…857)
> [!NOTE]
> **Top of a three-PR stack:** #858 (spec) → #856 (transfer deprecation)
→ this. Base is `claude/transfer-api-deprecation-docs-6ycamq`, so the
diff here is only the 3 files below. Each merge retargets this
automatically.
## The gap
Nothing in the docs said whether a given transfer produces an `INCOMING`
or an `OUTGOING` transaction. Worse, the Transaction Lifecycle page
contained **zero occurrences of the word "incoming"** — it described
only the outgoing flow, despite `INCOMING_PAYMENT.*` webhooks existing
and being referenced from six other pages.
## The rule
The type is keyed on the **destination**, regardless of source:
| Destination | `type` | Webhook family |
|---|---|---|
| Internal account | `INCOMING` | `INCOMING_PAYMENT.<STATUS>` |
| External account | `OUTGOING` | `OUTGOING_PAYMENT.<STATUS>` |
| UMA address | `OUTGOING` | `OUTGOING_PAYMENT.<STATUS>` |
Consequences worth spelling out, and now spelled out:
- A pull from an external account into an internal account is
`INCOMING`, even though the platform initiated it.
- A transfer between two internal accounts is `INCOMING`.
- A deposit that lands by paying an internal account's payment
instructions is `INCOMING`, as is a payment received at a customer's UMA
address.
This mirrors the dispatch in `gen_convert_to_transaction`
(`sparkcore/grid/objects/transaction.py:159`), which routes
`EntGridReceiveOperation` to incoming unconditionally and branches a
send operation on `gen_send_op_destination_is_internal_account`. That
helper carries the same truth table in its docstring at
`transaction.py:738`. The branch is gated on
`GK.GRID_INCOMING_TRANSACTION_REFACTOR`, which is rolled out, so the
table describes current behavior for all platforms.
## Changes
- **`transaction-lifecycle.mdx`** — new **Incoming or outgoing** section
at the top, ahead of the flow sections, since the type decides which
lifecycle and webhook family apply.
- **`transaction-lifecycle.mdx`** — split the webhook event table into
outgoing and incoming families. The incoming list was missing entirely.
Its `INCOMING_PAYMENT.PROCESSING` row corresponds to the enum value
added in #858.
- **`terminology.mdx`** — said the type was "from the platform's
perspective", which does not tell a reader how to predict it. Now states
the rule.
- **`list-transactions.mdx`** — the *Filter by transaction type* section
had the reader choosing `type=INCOMING|OUTGOING` with no way to know
which their payout is. Now states the rule and links to the table.
## Two things this PR previously got wrong
Recorded because both were corrected in place and a reviewer reading
only the head would not see them:
1. An early revision claimed incoming transactions have no `PROCESSING`
**state**. False — they do; both incoming converters map
`display_status` through, and
`gen_convert_send_op_to_incoming_transaction` maps `SENT` onto
`PROCESSING` explicitly (`transaction.py:891`). Only the *webhook event*
is missing.
2. The next revision then explained that missing event as an intentional
design difference, which would have enshrined a bug. It is a sparkcore
bug; #858 adds the enum and describes the emission fix.
## Validation
- `make lint` exits 0 — 663 problems, unchanged from baseline (all
pre-existing)
- Docs-only: no files under `openapi/`, so the bundle, oasdiff, and SDK
generation are untouched by this PR
- The `#incoming-or-outgoing` anchor is linked from
`list-transactions.mdx`; the heading carries no punctuation, so the slug
is unambiguous
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
ls-boltBot pushed a commit that referenced this pull request Aug 28, 2026
The SCA surface moved after this guide was written; bring it current:
- SCA login complete now requires `endUserIpAddress` and returns
`sessionExpiresAt` (#780); the session-scope guidance now tells
integrators to prompt re-login ahead of it.
- Quote authorize documents `409 SCA_SESSION_REQUIRED` and
`423 ACCOUNT_LOCKED` (#761); both join the error tables, and the
snippet notes authorizing requires an active login session.
- A challenge left to expire unsatisfied now fails the transaction with
`failureReason: SCA_NOT_COMPLETED` and no funds moved (#762).
- Trusted external accounts refuse `DELETE` with
`409 BENEFICIARY_TRUSTED`; untrust first (#770).
- The challenge lives on the quote, not the transaction — webhook
consumers route via the transaction's `quoteId` (#701).
- `POST /transfer-out` is deprecated in favor of `POST /quotes` with
`immediatelyExecute: true` (#856); the transfer-out tab now says so.
ls-boltBot pushed a commit that referenced this pull request Aug 29, 2026
The SCA surface moved after this guide was written; bring it current:
- SCA login complete now requires `endUserIpAddress` and returns
`sessionExpiresAt` (#780); the session-scope guidance now tells
integrators to prompt re-login ahead of it.
- Quote authorize documents `409 SCA_SESSION_REQUIRED` and
`423 ACCOUNT_LOCKED` (#761); both join the error tables, and the
snippet notes authorizing requires an active login session.
- A challenge left to expire unsatisfied now fails the transaction with
`failureReason: SCA_NOT_COMPLETED` and no funds moved (#762).
- Trusted external accounts refuse `DELETE` with
`409 BENEFICIARY_TRUSTED`; untrust first (#770).
- The challenge lives on the quote, not the transaction — webhook
consumers route via the transaction's `quoteId` (#701).
- `POST /transfer-out` is deprecated in favor of `POST /quotes` with
`immediatelyExecute: true` (#856); the transfer-out tab now says so.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-changeIntroduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@shreyav@pengying