Why
On staging, adding a bank account for a USD withdrawal failed with 422 BENEFICIARY_REJECTED. Airwallex POST /api/v1/beneficiaries/create returned validation_failed on beneficiary.bank_details.bank_account_category: the field is required for US ACH beneficiaries, and we did not send it.
Probing /api/v1/beneficiaries/validate on the sandbox, which creates nothing:
- missing → 400;
-
CHECKING→ 400 (value_options: ["Checking","Savings"]); -
Checking→ 200; -
Savings→ 200.
The values are case-sensitive.
What
-
BE:
CreateBankBeneficiaryDto.accountCategoryis required and accepts onlyCHECKINGorSAVINGS.AirwallexPayoutClientmaps it toCheckingorSavingsinbank_details.bank_account_category. - FE: "Account type" choice (Checking / Savings, default Checking) on the add-bank screen. The generated model is hand-edited to match the orval output, because staging swagger does not have the field yet.
- No DB column and no migration: the category is only needed when the beneficiary is created.
Compatibility
App builds that predate this change get a 400 from the new required field. No build with the bank-withdrawal screens has shipped to users, so nothing in the field breaks.
Tests
- BE:
yarn jest src/modules/fiat-payoutpasses (207 tests).yarn buildand eslint are clean. - FE:
pnpm jest src/components/withdrawpasses (47 tests), including a new add-bank screen test.tscand eslint are clean. - Mutation-checked: each new assertion fails when the mapping or the default is broken.
Opus review gate: PASS in round 1, with 0 blocking, 0 should-fix and 3 nits. The nits are parked:
- the radio pill should use
accessibilityState.checkedrather thanselected; -
import typeforBankAccountCategory; - the inline selector is verbose.
After merge
Retest on staging: add a bank account (routing 021000021), withdraw $11, then simulate PAID and FAILED in the Airwallex sandbox.