Skip to content

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

Merged
AaryamanBhute merged 1 commit into
mainfrom
07-13-plan-sandbox-card-event-simulate-endpoints
Jul 20, 2026
Merged

feat: sandbox simulate endpoints for the full card-event set#715
AaryamanBhute merged 1 commit into
mainfrom
07-13-plan-sandbox-card-event-simulate-endpoints

Conversation

@AaryamanBhute

Copy link
Copy Markdown
Contributor

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.

Original PR: #684

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 added bolt breaking-change Introduces a breaking change to the OpenAPI spec labels Jul 20, 2026
@vercel

vercel Bot commented Jul 20, 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 Jul 20, 2026 5:46pm
grid-wallet-demo Ignored Ignored Jul 20, 2026 5:46pm

Request Review

akanter commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

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

@AaryamanBhute
AaryamanBhute marked this pull request as ready for review July 20, 2026 17:46
@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 /customers/external-accounts/{externalAccountId}/trust

  • ⚠️ api path removed without deprecation

POST /customers/external-accounts/{externalAccountId}/trust/confirm

  • ⚠️ api path removed without deprecation

POST /customers/external-accounts/{externalAccountId}/untrust

  • ⚠️ api path removed without deprecation

POST /customers/external-accounts/{externalAccountId}/untrust/confirm

  • ⚠️ api path removed without deprecation

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

GET /sca/factors

  • ⚠️ api path removed without deprecation

POST /sca/factors

  • ⚠️ api path removed without deprecation

POST /sca/factors/confirm

  • ⚠️ api path removed without deprecation

POST /sca/factors/reset

  • ⚠️ api path removed without deprecation

GET /sca/factors/reset/{resetId}

  • ⚠️ api path removed without deprecation

POST /sca/factors/reset/{resetId}/complete

  • ⚠️ api path removed without deprecation

DELETE /sca/factors/{credentialId}

  • ⚠️ api path removed without deprecation

POST /sca/login/complete

  • ⚠️ api path removed without deprecation

POST /sca/login/start

  • ⚠️ api path removed without deprecation

POST /sca/record-event

  • ⚠️ api path removed without deprecation

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

@github-actions

github-actions Bot commented Jul 20, 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

feat(api): add response types to sandbox card simulate methods

kotlin

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

openapi

feat(api): add 6 sandbox card simulations, update authorization/clearing/return to async

php

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

python

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

ruby

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

typescript

fix(api): update return types for sandbox.cards.simulate methods
⚠️ grid-openapi studio · code

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

grid-ruby studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅build ✅lint ✅test ✅

⚠️ grid-go studio · 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@68ae88a32db984dae99e34f475af69c852ad0959
⚠️ grid-kotlin studio · 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-python studio · 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/87d7b81339a5864f9354b1f5a260b3e4830fbefb/grid-0.0.1-py3-none-any.whl
grid-typescript studio · conflict

Your SDK build had at least one note diagnostic.

grid-php studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅lint ✅test ✅

⚠️ grid-cli studio · code

Your SDK build had a failure in the test 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-07-20 18:15:24 UTC

@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR completes the sandbox card-event simulate surface by adding 7 new POST /sandbox/cards/{id}/simulate/* endpoints and correcting the 3 existing simulators (authorization, clearing, return) from a synchronous 200 / CardTransaction response to the correct asynchronous 202 / SandboxCardSimulationResponse shape.

  • 7 new endpoints (balance_inquiry, credit_authorization, financial_authorization, financial_credit_authorization, authorization_advice, credit_authorization_advice, return_reversal) with 4 new request schemas; SandboxCardAuthorizationRequest is cleanly shared by 5 of them.
  • Linter carve-outs are scoped correctly — both Spectral (regex second branch) and Redocly (lint-ignore) enumerate only the new snake_case segments, leaving the kebab-case rule intact for all other paths.
  • Breaking-change note on existing simulators: clients already parsing the 200 / CardTransaction response from authorization, clearing, or return will need to update to the 202 / { issuerTransactionToken } shape; the PR description calls this a "response correction" rather than a breaking change, but it is a contract change that should be communicated to any existing sandbox users.

Confidence Score: 4/5

Safe to merge with the understanding that the 200→202 response shape change on the three existing simulate endpoints is a visible contract change for any sandbox consumer already parsing those responses.

The new endpoints and schemas are well-structured, consistent, and pass lint. The only findings are two 404 description inconsistencies (missing the "(also returned in production for this path)" qualifier on authorization_advice and return_reversal) — cosmetic but worth fixing for documentation clarity. The more substantive point is that the 200→202 correction on the existing authorization, clearing, and return simulators is a real shape change; sandbox-only, but any client already parsing the old CardTransaction body will break.

The two new endpoint files sandbox_cards_{id}simulate_authorization_advice.yaml and sandbox_cards{id}_simulate_return_reversal.yaml have the minor 404 description inconsistency. The existing authorization, clearing, and return endpoint files are worth double-checking if any internal sandbox client depends on the old response shape.

Important Files Changed

Filename Overview
openapi/components/schemas/cards/SandboxCardAuthorizationAdviceRequest.yaml New schema for authorization_advice — correct use of OpenAPI 3.1 numeric exclusiveMinimum: 0 on amount, required fields match endpoint semantics.
openapi/components/schemas/cards/SandboxCardSimulationResponse.yaml New shared response schema (issuerTransactionToken) used consistently by all 10 simulate endpoints.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml New authorization_advice endpoint; 404 description missing the "(also returned in production for this path)" qualifier present on all other endpoints in this family.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml New return_reversal endpoint; same inconsistent 404 description as authorization_advice.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization.yaml Correctly updated from 200/CardTransaction to 202/SandboxCardSimulationResponse to match async delivery semantics.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_clearing.yaml Updated from 200/CardTransaction to 202/SandboxCardSimulationResponse — consistent correction.
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml Updated from 200/CardTransaction to 202/SandboxCardSimulationResponse — consistent correction.
.spectral.yaml Regex correctly extended with a second branch that exactly enumerates all 7 snake_case simulate paths, keeping the carve-out narrowly scoped.
.redocly.lint-ignore.yaml All 7 new snake_case simulate path keys added to the kebab-case ignore list — complete and correct.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant GridSandboxAPI as Grid Sandbox API
    participant CardIssuer as Card Issuer Sandbox
    participant Webhook as Client Webhook

    Client->>GridSandboxAPI: "POST /sandbox/cards/{id}/simulate/<event>"
    Note over GridSandboxAPI: Validates card id,<br/>request body, sandbox token
    GridSandboxAPI->>CardIssuer: Poke issuer sandbox simulate route
    CardIssuer-->>GridSandboxAPI: issuerTransactionToken
    GridSandboxAPI-->>Client: "202 { issuerTransactionToken }"
    Note over CardIssuer,Webhook: Async delivery
    CardIssuer->>Webhook: Card operation event (CardTransaction updated)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client
    participant GridSandboxAPI as Grid Sandbox API
    participant CardIssuer as Card Issuer Sandbox
    participant Webhook as Client Webhook

    Client->>GridSandboxAPI: "POST /sandbox/cards/{id}/simulate/<event>"
    Note over GridSandboxAPI: Validates card id,<br/>request body, sandbox token
    GridSandboxAPI->>CardIssuer: Poke issuer sandbox simulate route
    CardIssuer-->>GridSandboxAPI: issuerTransactionToken
    GridSandboxAPI-->>Client: "202 { issuerTransactionToken }"
    Note over CardIssuer,Webhook: Async delivery
    CardIssuer->>Webhook: Card operation event (CardTransaction updated)
Loading
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml:66-67
**Inconsistent 404 description missing production-context note**

The `authorization` endpoint (and all other new card-level simulate paths — `balance_inquiry`, `credit_authorization`, `financial_authorization`, `financial_credit_authorization`, `credit_authorization_advice`) use `"Card not found (also returned in production for this path)"` as their 404 description to clarify that a sandbox-only endpoint still returns 404 in production. Both `authorization_advice` and `return_reversal` use `"Card or card transaction not found"` without that qualifier. A caller reading only those two endpoint definitions won't know the production vs. sandbox behaviour differs.

### Issue 2 of 3
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml:68-69
The `return_reversal` 404 description is missing the production-context note used on all other endpoints in this family. The other card-level simulate endpoints follow the pattern `"Card or card transaction not found (also returned in production for this path)"`, but this one drops the parenthetical, leaving callers uncertain about production behaviour.

```suggestion
    '404':
      description: Card or card transaction not found (also returned in production for this path)
```

### Issue 3 of 3
openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml:66-67
Same issue as `return_reversal` — the 404 description is missing the `"(also returned in production for this path)"` qualifier that every other endpoint in this simulate family uses, including the existing `authorization` and all five other new endpoints.

```suggestion
    '404':
      description: Card or card transaction not found (also returned in production for this path)
```

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

Comment on lines +66 to +67
'404':
description: Card or card transaction not found

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.

P2 Inconsistent 404 description missing production-context note

The authorization endpoint (and all other new card-level simulate paths — balance_inquiry, credit_authorization, financial_authorization, financial_credit_authorization, credit_authorization_advice) use "Card not found (also returned in production for this path)" as their 404 description to clarify that a sandbox-only endpoint still returns 404 in production. Both authorization_advice and return_reversal use "Card or card transaction not found" without that qualifier. A caller reading only those two endpoint definitions won't know the production vs. sandbox behaviour differs.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml
Line: 66-67

Comment:
**Inconsistent 404 description missing production-context note**

The `authorization` endpoint (and all other new card-level simulate paths — `balance_inquiry`, `credit_authorization`, `financial_authorization`, `financial_credit_authorization`, `credit_authorization_advice`) use `"Card not found (also returned in production for this path)"` as their 404 description to clarify that a sandbox-only endpoint still returns 404 in production. Both `authorization_advice` and `return_reversal` use `"Card or card transaction not found"` without that qualifier. A caller reading only those two endpoint definitions won't know the production vs. sandbox behaviour differs.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +68 to +69
'404':
description: Card or card transaction not found

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.

P2 The return_reversal 404 description is missing the production-context note used on all other endpoints in this family. The other card-level simulate endpoints follow the pattern "Card or card transaction not found (also returned in production for this path)", but this one drops the parenthetical, leaving callers uncertain about production behaviour.

Suggested change
'404':
description: Card or card transaction not found
'404':
description: Card or card transaction not found (also returned in production for this path)
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_return_reversal.yaml
Line: 68-69

Comment:
The `return_reversal` 404 description is missing the production-context note used on all other endpoints in this family. The other card-level simulate endpoints follow the pattern `"Card or card transaction not found (also returned in production for this path)"`, but this one drops the parenthetical, leaving callers uncertain about production behaviour.

```suggestion
    '404':
      description: Card or card transaction not found (also returned in production for this path)
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +66 to +67
'404':
description: Card or card transaction not found

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.

P2 Same issue as return_reversal — the 404 description is missing the "(also returned in production for this path)" qualifier that every other endpoint in this simulate family uses, including the existing authorization and all five other new endpoints.

Suggested change
'404':
description: Card or card transaction not found
'404':
description: Card or card transaction not found (also returned in production for this path)
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/paths/sandbox/cards/sandbox_cards_{id}_simulate_authorization_advice.yaml
Line: 66-67

Comment:
Same issue as `return_reversal` — the 404 description is missing the `"(also returned in production for this path)"` qualifier that every other endpoint in this simulate family uses, including the existing `authorization` and all five other new endpoints.

```suggestion
    '404':
      description: Card or card transaction not found (also returned in production for this path)
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

AaryamanBhute commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jul 20, 6:09 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 20, 6:09 PM UTC: @AaryamanBhute merged this pull request with Graphite.

@AaryamanBhute
AaryamanBhute merged commit 9557e19 into main Jul 20, 2026
22 checks passed
@AaryamanBhute
AaryamanBhute deleted the 07-13-plan-sandbox-card-event-simulate-endpoints branch July 20, 2026 18:09
@claude claude Bot mentioned this pull request Jul 21, 2026
2 tasks
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.

3 participants