Skip to content

feat: sandbox simulate endpoints for the full card-event set#684

Draft
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-13-plan-sandbox-card-event-simulate-endpoints
Draft

feat: sandbox simulate endpoints for the full card-event set#684
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-13-plan-sandbox-card-event-simulate-endpoints

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Jul 13, 2026

Copy link
Copy Markdown

Summary

Adds the 7 remaining sandbox card-event simulate endpoints, completing the set alongside the existing authorization, clearing, and return simulators. Each is POST, sandbox-only, and returns 202 with { "issuerTransactionToken": string } — the simulate call drives the card issuer's sandbox and the resulting card operation is delivered asynchronously via webhook.

New endpoints (all under /sandbox/cards/{id}/simulate/):

Path Request body
balance_inquiry SandboxCardBalanceInquiryRequest (merchant only — a $0 inquiry)
credit_authorization SandboxCardAuthorizationRequest
financial_authorization SandboxCardAuthorizationRequest
financial_credit_authorization SandboxCardAuthorizationRequest
authorization_advice SandboxCardAuthorizationAdviceRequest (cardTransactionId + new total amount)
credit_authorization_advice SandboxCardAuthorizationRequest
return_reversal SandboxCardTransactionRefRequest (cardTransactionId)

New schemas: SandboxCardBalanceInquiryRequest, SandboxCardAuthorizationAdviceRequest, SandboxCardTransactionRefRequest, and a shared SandboxCardSimulationResponse ({ issuerTransactionToken }). SandboxCardAuthorizationRequest and CardMerchant are reused.

Response correction to the existing 3 simulators: they were documented as 200 returning a full CardTransaction, but these simulators are asynchronous — they return an issuer transaction token and deliver the resulting card operation over webhook. This PR corrects authorization, clearing, and return to 202 / SandboxCardSimulationResponse so the whole simulate family is consistent.

Intentionally excluded: authorization expiry and authorization reversal / void — neither has a card-issuer simulate path.

Notes

  • The simulate/* path segments are snake_case to match the card issuer's simulate routes verbatim, so they're exempted from the repo's kebab-case path convention (scoped carve-outs in .spectral.yaml and .redocly.lint-ignore.yaml, not a global relaxation).
  • No info.version bump: no breaking change to an existing published contract — this documents new endpoints and corrects the stale response shape on the existing simulators.

Test plan

  • make build — rebundles openapi.yaml + mintlify/openapi.yaml; both contain the 7 new paths, 7 operationIds, and the 4 new schemas.
  • make lint — passes (Redocly + Spectral + markdown), 0 errors.

@vercel

vercel Bot commented Jul 13, 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 Jul 17, 2026 7:47pm
grid-wallet-demo Ignored Ignored Preview Jul 17, 2026 7:47pm

Request Review

@ls-bolt ls-bolt Bot added the bolt label Jul 13, 2026

akanter commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

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

@ls-bolt
ls-bolt Bot force-pushed the 07-13-plan-sandbox-card-event-simulate-endpoints branch from 079aa28 to 61be3a2 Compare July 13, 2026 22:47
@ls-bolt ls-bolt Bot changed the title plan-sandbox-card-event-simulate-endpoints feat: sandbox simulate endpoints for the full card-event set Jul 13, 2026
@github-actions github-actions Bot added the breaking-change Introduces a breaking change to the OpenAPI spec label Jul 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

This PR introduces breaking changes to openapi.yaml:

API Changelog 2025-10-13 vs. 2025-10-13

API Changes

POST /sandbox/cards/{id}/simulate/authorization

  • ⚠️ removed the success response with the status 200

POST /sandbox/cards/{id}/simulate/clearing

  • ⚠️ removed the success response with the status 200

POST /sandbox/cards/{id}/simulate/return

  • ⚠️ removed the success response with the status 200

Detected by oasdiff. This PR will need approval from an API reviewer before merge.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

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

cli

chore(internal): regenerate SDK with no functional changes

go

fix(api): update return types for sandbox card simulate methods

kotlin

fix(api): update return types for sandbox cards simulate methods

openapi

feat(api): add 7 sandbox card simulations, update 3 existing to async responses

php

fix(types): use specific response types for sandbox cards simulate methods

python

fix(types): correct return types for sandbox cards simulate methods

ruby

fix(api): correct return types for sandbox cards simulate methods

typescript

fix(types): correct return types in sandbox.cards.simulate methods

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/68a9e31bb44a858a18b2ff596de279b5dcb0bb5b/dist.tar.gz
New diagnostics (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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 (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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 (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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@9fddf6ccc1783896f0fc98263192e81212066054
New diagnostics (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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 (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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/2d00b0360d70a2f9f2bafe670bbf6223e6f4a7ad/grid-0.0.1-py3-none-any.whl
New diagnostics (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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 (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`
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 (7 note)
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/balance_inquiry`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/financial_credit_authorization`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/credit_authorization_advice`
💡 Endpoint/NotConfigured: Skipped endpoint because it's not in your Stainless config: `post /sandbox/cards/{id}/simulate/return_reversal`

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-07-17 19:53:58 UTC

@ls-bolt

ls-bolt Bot commented Jul 13, 2026

Copy link
Copy Markdown
Author

Heads-up for whoever claims/publishes this: the Stainless preview bot derives each SDK's changelog message from the branch name, so it currently shows feat: plan-sandbox-card-event-simulate-endpoints (the branch has a plan- prefix from the planning phase). The bot regenerates on each push, so editing the comment doesn't stick. To get clean SDK changelogs, either publish from a branch without the plan- prefix (e.g. on reauthor/claim) or edit the Stainless comment right before merge. The PR title and commit message are already clean.

@ls-bolt

ls-bolt Bot commented Jul 17, 2026

Copy link
Copy Markdown
Author

@greptile review

@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR completes the sandbox card-event simulator family by adding 7 new POST /sandbox/cards/{id}/simulate/* endpoints alongside the existing authorization, clearing, and return simulators. It also corrects those 3 existing endpoints from a synchronous 200 / CardTransaction response shape to the accurate asynchronous 202 / SandboxCardSimulationResponse ({ issuerTransactionToken }).

  • 7 new endpoints (balance_inquiry, credit_authorization, financial_authorization, financial_credit_authorization, authorization_advice, credit_authorization_advice, return_reversal) added with correct request schemas, 202 responses, and consistent error response sets (400 / 401 / 403 / 404 / 500).
  • 4 new schemas introduced: SandboxCardBalanceInquiryRequest, SandboxCardAuthorizationAdviceRequest, SandboxCardTransactionRefRequest, and the shared SandboxCardSimulationResponse; SandboxCardAuthorizationRequest is reused for the authorization-family endpoints.
  • Kebab-case linting exemptions correctly scoped to the 7 snake_case paths in both .spectral.yaml (via a second regex branch) and .redocly.lint-ignore.yaml, leaving the 3 existing kebab-compatible simulate paths untouched.

Confidence Score: 5/5

Safe to merge — adds sandbox-only simulate endpoints with no changes to production paths, and the response-shape correction on the 3 existing simulators is a documentation fix that aligns with the actual async contract.

All changes are additive (7 new sandbox endpoints) or corrective (3 existing sandbox endpoints updated from incorrect 200/CardTransaction to 202/SandboxCardSimulationResponse). The new schemas are correctly typed for OpenAPI 3.1. Linting exemptions are scoped tightly. No production paths are touched, no version bump is needed, and the PR description accounts for all intentional design choices.

No files require special attention.

Important Files Changed

Filename Overview
openapi/openapi.yaml 7 new path $refs added in the paths section; ordered logically after the existing simulate endpoints and before /stablecoin-provider-accounts.
.spectral.yaml paths-kebab-case rule updated to a two-branch regex: the original branch covers all standard paths, a new branch whitelists the 7 snake_case simulate paths. Exemption is correctly scoped (not a blanket relaxation).
.redocly.lint-ignore.yaml Redocly paths-kebab-case ignore entries added for all 7 new snake_case simulate paths; consistent with the Spectral exemption scope.
openapi/components/schemas/cards/SandboxCardSimulationResponse.yaml New shared response schema with a single required issuerTransactionToken string; clean and correctly applied across all 10 simulate endpoints.
openapi/components/schemas/cards/SandboxCardAuthorizationAdviceRequest.yaml New schema for authorization advice; requires cardTransactionId and total amount with exclusiveMinimum: 0 (valid OpenAPI 3.1 JSON Schema semantics).
openapi/components/schemas/cards/SandboxCardAuthorizationRequest.yaml Updated description to list all 5 authorization-family endpoints that reuse this schema; no property changes.
openapi/components/schemas/cards/SandboxCardBalanceInquiryRequest.yaml New schema for balance inquiry; merchant-only (no amount), consistent with $0 implicit nature of balance inquiries.
openapi/components/schemas/cards/SandboxCardTransactionRefRequest.yaml New schema keyed only by cardTransactionId; used for return_reversal, correctly scoped and described.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization.yaml Corrected from 200/CardTransaction to 202/SandboxCardSimulationResponse to reflect the actual async behavior.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_clearing.yaml Corrected from 200/CardTransaction to 202/SandboxCardSimulationResponse; response description updated to reflect async delivery.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml Corrected from 200/CardTransaction to 202/SandboxCardSimulationResponse; response description updated to reflect async delivery.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml New endpoint for authorization advice simulation; uses the correct SandboxCardAuthorizationAdviceRequest schema, 202 response, and full error set.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_balance_inquiry.yaml New endpoint for balance inquiry simulation; correctly uses merchant-only SandboxCardBalanceInquiryRequest (no amount, as $0 is implicit), 202 response, full error set.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_credit_authorization.yaml New endpoint for credit authorization simulation; reuses SandboxCardAuthorizationRequest schema consistently with the authorization-family pattern.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_credit_authorization_advice.yaml New endpoint for credit authorization advice; intentionally uses SandboxCardAuthorizationRequest (PAN+merchant keyed, not transaction-keyed) as described in the PR.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_financial_authorization.yaml New endpoint for single-message financial authorization simulation; correctly uses SandboxCardAuthorizationRequest and 202 response.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_financial_credit_authorization.yaml New endpoint for single-message financial credit authorization simulation; correctly uses SandboxCardAuthorizationRequest and 202 response.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml New endpoint for return reversal simulation; uses SandboxCardTransactionRefRequest (cardTransactionId only), 202 response, and correctly notes the REFUNDED state prerequisite.

Reviews (2): Last reviewed commit: "feat: sandbox simulate endpoints for the..." | Re-trigger Greptile

Add 7 sandbox card-event simulate endpoints, mirroring the existing
authorization/clearing/return simulators: balance_inquiry,
credit_authorization, financial_authorization, financial_credit_authorization,
authorization_advice, credit_authorization_advice, return_reversal. All POST,
sandbox-only, 202 -> { issuerTransactionToken }.

Correct the existing 3 simulators' documented success response from
200/CardTransaction to 202/SandboxCardSimulationResponse to match the actual
issuer-driven, webhook-delivered behavior.

Authorization expiry and authorization reversal/void are intentionally excluded
(no card-issuer simulate path).

Co-Authored-By: aaryamanbhute <aaryamanbhute@users.noreply.github.com>
@ls-bolt
ls-bolt Bot force-pushed the 07-13-plan-sandbox-card-event-simulate-endpoints branch from 61be3a2 to af66b87 Compare July 17, 2026 19:47
@ls-bolt

ls-bolt Bot commented Jul 17, 2026

Copy link
Copy Markdown
Author

@greptile review

@mintlify

mintlify Bot commented Jul 17, 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 Jul 17, 2026, 7:48 PM

@mintlify

mintlify Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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

Project Status Preview Updated (UTC)
Grid 🟡 Building Jul 17, 2026, 7:47 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bolt breaking-change Introduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants