Skip to content

Add SLV_ACCOUNT external-account type for El Salvador#462

Closed
mohamedwane wants to merge 1 commit into
mainfrom
mohamed/slv-external-account-schema
Closed

Add SLV_ACCOUNT external-account type for El Salvador#462
mohamedwane wants to merge 1 commit into
mainfrom
mohamed/slv-external-account-schema

Conversation

@mohamedwane
Copy link
Copy Markdown
Contributor

Summary

Adds the OpenAPI schemas for `SLV_ACCOUNT`, the external-account type for El Salvador Thunes payouts. The sparkcore destination resolver at thunes_destination_resolver.py:30 already maps `SLV_ACCOUNT → $grid.slv`, but until now there was no schema for clients to create such accounts. This is the foundation needed before we can wire SLV in sparkcore and finally turn the corridor on for testing.

Design notes

El Salvador uses USD as its currency, which Lightspark also uses for the US bank corridor. To avoid touching the existing US flow, `SLV_ACCOUNT` is modeled as a separate `accountType` under the same `USD` currency. The dispatch on accountType is what distinguishes routes:

  • `USD_ACCOUNT` → Lightspark Payments (existing US ACH/wire flow, untouched)
  • `SLV_ACCOUNT` → Thunes via $grid.slv (new)

No new `CurrencyUnit` is introduced, no schema for US bank flow is modified.

Schema layout

Mirrors the recent GHS/BDT refactor (per-rail conditional fields):

File Purpose
`common/SlvAccountInfoBase.yaml` Multi-rail base: `bankName`/`accountNumber`/`bankAccountType` for BANK_TRANSFER, `phoneNumber` for MOBILE_MONEY (Tigo Money)
`common/SlvAccountInfo.yaml` Adds `paymentRails` array for response shape
`common/SlvBeneficiary.yaml` Individual beneficiary, mirrors GHS/BDT/HTG
`common/PaymentSlvAccountInfo.yaml` Payment-instruction variant (with `reference`)
`external_accounts/SlvExternalAccountCreateInfo.yaml` POST create body
`external_accounts/SlvExternalAccountInfo.yaml` Account response
`ExternalAccountType.yaml` + `SLV_ACCOUNT` enum value
`ExternalAccountCreateInfoOneOf.yaml` + `SLV_ACCOUNT` discriminator mapping
`ExternalAccountInfoOneOf.yaml` + `SLV_ACCOUNT` discriminator mapping
`PaymentInstructions.yaml` + `SLV_ACCOUNT` discriminator mapping

Bundled `openapi.yaml` regenerated via `npm run build:openapi`; mintlify copy updated.

Test plan

  • `npm run lint:openapi` passes (no errors, 16 unrelated warnings, 1 ignored)
  • Bundled spec contains all SLV refs and discriminator mappings
  • Regenerate the sparkcore Python SDK (`grid-api/grid_api/models/`) before the follow-up sparkcore PR can land

Follow-up

Sparkcore PR will:

  1. Add `SlvExternalAccountInfo`/`SlvExternalAccountCreateInfo` import + tuple to `CURRENCY_TO_ACCOUNT_TYPE[CurrencyUnit.USD]` so the dispatcher accepts both US and SLV account shapes under USD
  2. Add SLV branch to `thunes_fields_provider._bank_receiver_fields` and `_mobile_receiver_fields` (keyed on `CurrencyUnit.USD` — safe since `ThunesFieldsProvider` is only consumed by Thunes flows, not by LSP USD)
  3. Flip `THUNES_CORRIDOR_RAILS["$grid.slv"] = [RailType.BANK, RailType.MOBILE_MONEY]`
  4. Account-creation plumbing in `grid/utils/account.py` to build `SlvExternalAccountInfo` responses
  5. Add USD entry to `CURRENCY_PAYEE_FIELD_MAPPINGS` for SLV's CPI fields

🤖 Generated with Claude Code

The Thunes destination resolver already maps SLV_ACCOUNT → $grid.slv
in sparkcore, but there was no OpenAPI schema for clients to create
SLV accounts with. Add it now so we can unblock end-to-end testing
of the El Salvador corridor.

SLV runs on USD but is a distinct payout corridor from Lightspark's
US bank flow (which uses USD_ACCOUNT). Modeled as a separate
accountType under the same USD currency so the existing US flow is
untouched and disambiguation happens at the destination-resolution
layer, not at the currency layer.

Schemas mirror the recent GHS/BDT shape: per-rail-conditional
required fields (bankAccountType + accountNumber for BANK_TRANSFER,
phoneNumber for MOBILE_MONEY/Tigo Money). Beneficiary follows the
existing Thunes-corridor pattern.

Files:
- common/SlvAccountInfoBase.yaml — multi-rail base fields
- common/SlvAccountInfo.yaml — adds paymentRails for response shape
- common/SlvBeneficiary.yaml — Individual beneficiary, INDIVIDUAL discriminator
- common/PaymentSlvAccountInfo.yaml — payment-instruction variant
- external_accounts/SlvExternalAccountCreateInfo.yaml — create payload
- external_accounts/SlvExternalAccountInfo.yaml — response payload
- ExternalAccountType.yaml — add SLV_ACCOUNT enum value
- ExternalAccountCreateInfoOneOf.yaml — register in create discriminator
- ExternalAccountInfoOneOf.yaml — register in response discriminator
- PaymentInstructions.yaml — register in payment discriminator
@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

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

Project Deployment Actions Updated (UTC)
grid-flow-builder Ready Ready Preview, Comment May 12, 2026 10:50pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

✱ Stainless preview builds for grid

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

kotlin

feat(api): add SlvAccount variant to external accounts models

openapi

feat(api): add SLV account support to payment/external account types

python

feat(api): add SLV account type to external accounts and payment instructions

typescript

feat: Add SLV_ACCOUNT external-account type for El Salvador

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

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/7f991a7a2a9a74d6704b685f4ce93ff32ab6492f/grid-0.0.1-py3-none-any.whl
New diagnostics (5 note)
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvExternalAccountCreateInfo`
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvBeneficiary`
grid-kotlin studio · code · diff

generate ❗build ⏳lint ⏳test ⏳

New diagnostics (12 note)
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvExternalAccountCreateInfo`
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvBeneficiary`
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 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 (5 note)
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvExternalAccountCreateInfo`
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvBeneficiary`
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 ❗

New diagnostics (5 note)
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Schema/RequiredPropertyNotDefined: This schema marks `accountType` as `required`, but it isn't defined in `properties`, so it will be ignored.
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvExternalAccountCreateInfo`
💡 Model/Recommended: We recommend you use a model for `#/components/schemas/SlvBeneficiary`

⏳ These are partial results; builds are still running.


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-05-12 22:53:23 UTC

@mohamedwane
Copy link
Copy Markdown
Contributor Author

Superseded by fresh branch with cleaner name; reopening as draft.

@mohamedwane mohamedwane deleted the mohamed/slv-external-account-schema branch May 12, 2026 22:53
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 12, 2026

Greptile Summary

This PR introduces SLV_ACCOUNT as a new external-account type for El Salvador Thunes payouts, adding the full OpenAPI schema layer that was previously missing before the sparkcore corridor can be enabled.

  • New schemas added: SlvAccountInfoBase (bank + mobile fields), SlvAccountInfo (adds paymentRails for responses), SlvBeneficiary, PaymentSlvAccountInfo, SlvExternalAccountCreateInfo, and SlvExternalAccountInfo — all following the established GHS/BDT/HTG pattern precisely.
  • Discriminator wiring: SLV_ACCOUNT is registered in ExternalAccountType, ExternalAccountCreateInfoOneOf, ExternalAccountInfoOneOf, and PaymentInstructions discriminator mappings; placement and mapping paths are consistent with existing corridor entries.

Confidence Score: 5/5

Safe to merge — pure schema additions with no changes to existing account types or flows.

All six new schema files faithfully mirror the GHS/BDT/HTG corridor pattern: the create schema uses the base (no paymentRails), the response schema uses the enriched shape (with paymentRails), the discriminator mappings are complete in all four registries, and the phone-number regex and El Salvador country-code example are correct. No existing schema is modified beyond appending one entry to each list/mapping.

No files require special attention.

Important Files Changed

Filename Overview
openapi/components/schemas/common/SlvAccountInfoBase.yaml Core SLV account fields — bankName/accountNumber/bankAccountType for BANK_TRANSFER, phoneNumber for MOBILE_MONEY; mirrors GHS/BDT pattern, phone pattern and El Salvador country-code example are correct
openapi/components/schemas/common/SlvAccountInfo.yaml Adds required paymentRails array to the base for the response shape; consistent with GhsAccountInfo.yaml
openapi/components/schemas/common/SlvBeneficiary.yaml Individual beneficiary schema — identical structure to GhsBeneficiary/BdtBeneficiary/HtgBeneficiary, following the established per-corridor pattern
openapi/components/schemas/common/PaymentSlvAccountInfo.yaml Payment-instruction variant composing BasePaymentAccountInfo + SlvAccountInfo + required reference field; mirrors PaymentGhsAccountInfo exactly
openapi/components/schemas/external_accounts/SlvExternalAccountCreateInfo.yaml Create-request body composing BaseExternalAccountInfo + SlvAccountInfoBase (no paymentRails, consistent with other create schemas) + required beneficiary discriminator
openapi/components/schemas/external_accounts/SlvExternalAccountInfo.yaml Response shape composing BaseExternalAccountInfo + SlvAccountInfo (includes paymentRails) + required beneficiary discriminator
openapi/components/schemas/external_accounts/ExternalAccountType.yaml SLV_ACCOUNT enum value added after PKR_ACCOUNT, maintaining alphabetical ordering
openapi/components/schemas/external_accounts/ExternalAccountCreateInfoOneOf.yaml SLV_ACCOUNT added to both oneOf list and discriminator mapping — wiring is complete and correct
openapi/components/schemas/external_accounts/ExternalAccountInfoOneOf.yaml SLV_ACCOUNT added to both oneOf list and discriminator mapping — wiring is complete and correct
openapi/components/schemas/common/PaymentInstructions.yaml SLV_ACCOUNT added to oneOf list and discriminator mapping; insertion between PKR and EMBEDDED_WALLET is consistent with ordering in other discriminator files

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
  class SlvAccountInfoBase {
    +accountType: SLV_ACCOUNT
    +bankName: string
    +accountNumber: string
    +bankAccountType: CHECKING|SAVINGS
    +phoneNumber: string
  }
  class SlvAccountInfo {
    +paymentRails: array
  }
  class SlvExternalAccountCreateInfo {
    +beneficiary: SlvBeneficiary|BusinessBeneficiary
  }
  class SlvExternalAccountInfo {
    +beneficiary: SlvBeneficiary|BusinessBeneficiary
  }
  class PaymentSlvAccountInfo {
    +reference: string
  }
  class BaseExternalAccountInfo
  class BasePaymentAccountInfo

  SlvAccountInfo --|> SlvAccountInfoBase : allOf
  SlvExternalAccountCreateInfo --|> BaseExternalAccountInfo : allOf
  SlvExternalAccountCreateInfo --|> SlvAccountInfoBase : allOf
  SlvExternalAccountInfo --|> BaseExternalAccountInfo : allOf
  SlvExternalAccountInfo --|> SlvAccountInfo : allOf
  PaymentSlvAccountInfo --|> BasePaymentAccountInfo : allOf
  PaymentSlvAccountInfo --|> SlvAccountInfo : allOf
Loading

Reviews (1): Last reviewed commit: "Add SLV_ACCOUNT external-account type fo..." | Re-trigger Greptile

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant