feat: document BENEFICIARY_TRUSTED (409) on customer external-account delete - #770
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript ✅ grid-ruby studio · code
|
Co-Authored-By: jklein24 <jklein24@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Your wording change is better than mine — kept it verbatim. The build check was failing because the bundles are generated from Pushed the rebundle ( |
|
Its log shows the deploy itself succeeding and only the last CDN step failing: And the preview site is in fact live and serving the new response —
So it's a page-revalidation flake on Mintlify's side. It's posted by the Mintlify GitHub app rather than an Actions workflow, so I can't re-run it from here — a push or a nudge from you on their side should clear it. Flagging rather than papering over it in case you'd rather it be green before merging. |
Greptile SummaryUNTRUST, CONFIRM, DELETE — THEN LET THE 409 SILENCE BREAK.
Confidence Score: 5/5The PR appears safe to merge with the source specification and both generated bundles consistently documenting the existing conflict response. The new response references the established shared Error409 schema, the error code is present in both its enum and documentation table, the prescribed untrust/confirm endpoints match the existing API flow, and both generated bundles remain synchronized.
|
| Filename | Overview |
|---|---|
| openapi/paths/customers/customers_external_accounts_{externalAccountId}.yaml | Adds the documented 409 response and accurate untrust/confirm remediation for deleting a trusted beneficiary. |
| openapi/components/schemas/errors/Error409.yaml | Adds BENEFICIARY_TRUSTED consistently to the shared 409 enum and its documentation table. |
| openapi.yaml | Correctly reflects the source path and Error409 schema changes in the generated root bundle. |
| mintlify/openapi.yaml | Remains synchronized with the generated root OpenAPI bundle for local Mintlify rendering. |
Reviews (1): Last reviewed commit: "Rebundle openapi.yaml after the descript..." | Re-trigger Greptile
|
📌 Bolt Status 2026-07-30 16:18:30 UTC — ⚡ Agent |
|
Status after the approval, since the checks still show one red: this is merge-ready.
I tried to re-request that check run directly and got a 403 — it's owned by the Mintlify app, so One sequencing note: this spec PR should land before webdev #31456 (the implementation), so the documented |
… examples (#793) ## Summary Two things, both docs-only. Generated bundles untouched. 1. **Documents `GET` and `DELETE` for a single external account** — `external-accounts.mdx` covered create and list but neither by-id operation. 2. **Fixes all 85 remaining broken curl auth examples** across 17 files. **Replaces #359**, which should be closed. ## Part 1 — the new sections | Section | Covers | |---|---| | Retrieving a single external account | `GET /customers/external-accounts/{externalAccountId}`, full response example, `404` | | Deleting an external account | `DELETE /customers/external-accounts/{externalAccountId}`, `204`, and the `409 BENEFICIARY_TRUSTED` path | **Why a rewrite rather than a rebase of #359.** That PR has been open since April and the spec moved under it in four ways: 1. **It documents a `PATCH` endpoint that does not exist.** The path exposes only `get:` and `delete:` — verified in both the source path file and the bundled `openapi.yaml`. About a third of that PR describes an operation the API doesn't have. 2. **`"accountType": "US_ACCOUNT"`** is not a member of `ExternalAccountType`. The value is `USD_ACCOUNT`. 3. **`"accountCategory": "CHECKING"`** is not a field on `UsdAccountInfoBase`. The real field is `bankAccountType`. 4. **Delete's contract changed.** #770 added a `409`, which #359 predates. **The `409` is why the delete section earns its place.** `BENEFICIARY_TRUSTED` fires when the account is a trusted SCA beneficiary, and the caller must untrust *and* confirm before delete succeeds. Nothing at the call site hints at that. **The GET example includes `paymentRails`** because the response genuinely carries it — `UsdExternalAccountInfo` composes `UsdAccountInfo`, which requires it. A short `<Info>` notes it's returned rather than sent; that distinction has already caused one real bug. Every field traces to a schema: `ExternalAccount` for the envelope, `UsdAccountInfoBase` for account fields, `UsdAccountInfo` for `paymentRails` (`ACH`/`WIRE`/`RTP`/`FEDNOW`), `UsdBeneficiary` for the minimum beneficiary shape. ## Part 2 — the curl auth sweep Greptile flagged the auth header on the new examples. It was right, and the problem turned out to be repo-wide: **85 curl examples across 17 files** used ```bash -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' ``` which fails **two** independent ways. The single quotes stop the shell expanding the variables; and Basic auth requires `base64(user:pass)`, not the raw pair, so the header is rejected even once expanded. Every one of these failed on copy-paste — which is the entire point of a curl example. All 85 now use `-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"`. **This converges on the existing majority rather than introducing a style.** `api-reference/authentication.mdx` documents `curl -u "{client_id}:{client_secret}"`, and 178 examples across 40 other files already use `-u`. The `-H` form was the minority pattern. Biggest concentrations: `snippets/external-accounts.mdx` (26), `payouts-and-b2b/payment-flow/list-transactions.mdx` (15), `rewards/developer-guides/listing-transactions.mdx` (8). ## Verification - **85 replacements, 85 lines added, 85 deleted** — strictly 1:1, no line lost or merged - Zero occurrences of the broken form remain - **Only auth lines changed** — diff contains no other removals, so no `-H 'Content-Type'` was clobbered - **The 11 JS/Python `Basic ${credentials}` usages are untouched.** Those build the header from a pre-encoded value and are correct; the sweep matched only `-H` lines carrying the raw credential pair - No curl block ended up with a duplicate `-u` - MDX component tags and code fences balance across every `.mdx` in `mintlify/` - The new JSON example parses - Generated bundles byte-identical to `main` **Not verified:** no visual render check, and `make lint` was not run — it fails on `main` regardless, because `npx spectral lint` resolves to a stub `spectral@0.0.0` rather than `@stoplight/spectral-cli`. This change touches no OpenAPI source, so the Mintlify preview is the meaningful check. ## Still open in this file `external-accounts.mdx` documents 21 of ~37 account types in `account-types.ts`. Missing: `XAF`, `BWP`, `AED`, `BDT`, `EGP`, `GHS`, `GTQ`, `HTG`, `JMD`, `PKR`, `CNY`, plus wallet types `BASE_WALLET`, `POLYGON_WALLET`, `PLASMA_WALLET`, `SOLANA_WALLET`, `TRON_WALLET`, `ETHEREUM_WALLET`. Out of scope here, but it's the largest remaining documentation gap in this area. --------- Co-authored-by: Claude <noreply@anthropic.com>

Summary
DELETE /customers/external-accounts/{externalAccountId}can return409when the account is currently a trusted beneficiary, but the spec declared only204/401/404/500. This documents the missing status and its error code.BENEFICIARY_TRUSTEDadded to the sharedError409codeenum. Because it was absent, a generated client would raise a validation error while deserializing the response instead of surfacing a code the integrator can branch on.deleteoperation now declares409and itsdescriptionstates the ordering requirement: an account that is currently a trusted beneficiary must be untrusted first, viaPOST /customers/external-accounts/{externalAccountId}/untrust(and its/confirm), before it can be deleted.Trust cannot be revoked as a side effect of a delete — untrusting a beneficiary requires the customer to complete a Strong Customer Authentication challenge, which a
DELETEhas no way to carry. So the delete is refused while trust is in place rather than leaving the account deleted but still trusted.Both changes are additive and non-breaking, so
info.versionstays2025-10-13.Test plan
make lintexits 0 (Redocly + Spectral,--fail-severity=error): 632 findings, 0 errors, all pre-existing warnings/infos.make buildrebundledopenapi.yamlandmintlify/openapi.yaml; re-running it is a no-op, so the committed bundles byte-match the build output.409/BENEFICIARY_TRUSTEDpair is covered by tests asserting the status and code at the HTTP boundary, alongside the trust → refused-delete → untrust → successful-delete lifecycle.Public
Documents a
409 BENEFICIARY_TRUSTEDresponse onDELETE /customers/external-accounts/{externalAccountId}: an external account that is currently a trusted beneficiary must be untrusted before it can be deleted.Requested by @jklein24
Original PR: #769