Skip to content

feat: add rule-based internal accounts and the sweep failure webhook - #835

Draft
ls-bolt[bot] wants to merge 1 commit into
mainfrom
08-14-grid-rule-based-accounts-schema
Draft

feat: add rule-based internal accounts and the sweep failure webhook#835
ls-bolt[bot] wants to merge 1 commit into
mainfrom
08-14-grid-rule-based-accounts-schema

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the API surface for rule-based internal accounts — an additional account number for an existing customer with a routing rule attached, so incoming payments can be attributed to a specific payer and forwarded automatically.

Every schema change the feature needs is bundled here, in one reviewable PR, rather than arriving in pieces.

What's added

RULE_BASED on InternalAccountType, plus the same value as a type filter on GET /customers/internal-accounts.

POST /customers/internal-accounts — a new method on the existing path. The body takes customerId, type, and currency, an optional label, and a sweepRule describing where funds are forwarded: a destination (account id plus an optional payment rail) and optional purposeOfPayment, description, and remittanceInformation. Idempotency-Key is required, matching the other endpoints that mint something irreversible.

Only RULE_BASED is creatable. The other account types are provisioned automatically when a customer is created or approved, so the endpoint rejects them with a specific message rather than a generic error.

SWEEP.FAILED webhook — fired whenever a settled payment does not reach the rule's destination, including when the balance is below the corridor minimum and gets consolidated into the customer's main account instead. The payload carries both transaction ids, a reason, and an outcome, so an integrator can distinguish "this payment failed" from "and therefore this amount is somewhere else now."

Delivery is at-least-once and a redelivery carries a new event id, so the payload documents deduplicating on incomingTransactionId.

Two decisions worth a second opinion

DESTINATION_UNAVAILABLE is not included. It appeared in the original design, but nothing in the implementation can produce it — rail validation raises a single condition that NO_ELIGIBLE_RAIL already covers. Publishing a value that never arrives costs a permanently un-removable enum member (adding one is non-breaking; removing one is not) and generates a dead case in every SDK. Adding it later, if a rail ever produces it, is free. Happy to reserve it if you'd rather.

ABOVE_MAXIMUM is included and wasn't in the original design. A balance over the corridor ceiling would otherwise be submitted whole, rejected, and stranded; it now consolidates instead, and this is how the platform is told.

What's deliberately not here

GET /customers/internal-accounts/{id} and DELETE were in the original design but are not implemented. Speccing them now would generate SDK methods that 405, so they're left for whenever the endpoints land.

Verification

make lint passes with 0 errors, and zero warnings or informational findings on any schema added here. The root and Mintlify bundles are regenerated via make build, never hand-edited. All 1,922 $refs resolve.

@mintlify

mintlify Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

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

Project Status Preview Updated (UTC)
Grid 🟢 Ready View Preview Aug 14, 2026, 5:33 AM

@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

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

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Aug 14, 2026 5:32am
grid-wallet-demo Ignored Ignored Preview Aug 14, 2026 5:32am

Request Review

@ls-bolt ls-bolt Bot added the bolt label Aug 14, 2026
@ls-bolt
ls-bolt Bot force-pushed the 08-14-grid-rule-based-accounts-schema branch from a0a2b64 to 3ada236 Compare August 14, 2026 05:32
@github-actions github-actions Bot added breaking-change Introduces a breaking change to the OpenAPI spec and removed breaking-change Introduces a breaking change to the OpenAPI spec labels Aug 14, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

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

cli

feat(api): add RULE_BASED type to customers list_internal_accounts

go

feat(api): add RULE_BASED type to internal accounts, sweep webhook event

kotlin

feat(api): add RULE_BASED type to internal accounts, SWEEP.FAILED webhook event

openapi

feat(api): add customer internal account creation, sweep webhook, RULE_BASED account type

php

feat(api): add RULE_BASED account type and sweep webhook event

python

feat(api): add SweepWebhookEvent, RULE_BASED account type filter

ruby

feat(api): add sweep webhook event, RULE_BASED type to internal accounts

typescript

feat(api): add SweepWebhookEvent, RULE_BASED type to internal accounts

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

grid-typescript studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅build ✅lint ❗test ✅

npm install https://pkg.stainless.com/s/grid-typescript/6c48bae33a2acd08c1d071a6dca27b8ef7d9033a/dist.tar.gz
New diagnostics (1 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
grid-kotlin studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ⚠️build ✅lint ✅test ❗

New diagnostics (2 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-php studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅lint ✅test ✅

New diagnostics (2 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-openapi studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ⚠️

New diagnostics (1 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
grid-ruby studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅build ✅lint ✅test ✅

New diagnostics (1 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
grid-go studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@f331d9bc06ed3e20dcc4f82c00cc4c9ffdd8ac24
New diagnostics (2 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-python studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/6e24602ede861f9f06a62a438e62b066a1f0d5b2/grid-0.0.1-py3-none-any.whl
New diagnostics (1 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`
grid-cli studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ⚠️build ❗lint ❗test ❗

New diagnostics (1 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /customers/internal-accounts`

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-14 05:37:46 UTC

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.

2 participants