Get a list of supported FlashFlow banks, then process online FlashFlow purchases and payouts using Pay by Bank.
You can submit a FlashFlow transaction in these ways:
- Purchase (pay-in): Create a pay-by-bank transaction with
apmProviderset toFlashflowandintentset toPurchase. SupplybankName(the bank code from the bank-list route) andbankAccountNumber. RenderfundingData.payByBank.iframeSrcfrom the response in your own UI so the shopper can complete the pay-in. - Payout (withdrawal), new bank account: Create a pay-by-bank transaction with
intentset toPayoutand supply all three ofbankName,bankAccountNumber, andbankAccountHolderName. Don't also sendgatewayTokenId. CapturefundingData.payByBank.gatewayTokenIdfrom the response to reuse the destination later. - Payout (withdrawal), stored bank account: Create a payout and supply
gatewayTokenIdfrom an earlier accepted payout, or from a completed FlashFlow pay-in webhook or query when vaulted, instead of resending bank details.
FlashFlow supports THB only. Purchase examples use Thai shopper details (countryCode TH). Treat merchant webhooks as the authoritative final outcome. Don't treat the shopper completing the iframeSrc surface as payment confirmation on its own. You can use the Get transaction details API later for reconciliation.
Note that FlashFlow doesn't support capture, void, or refund.
Call this before creating FlashFlow pay-ins or payouts that need a bank code. Use each bank's code value as fundingData.payByBank.bankName when you create a transaction. Don't send the bank's display name.
curl --request GET \
--url 'https://api-services.pxp.io/api/v1/altp-flashflow-processor/MERCHANT-1/SITE-1/bank-list' \
--header 'accept: application/json'| Parameter | Description |
|---|---|
merchantstring (≤ 10 characters) required | Your unique merchant identifier, as assigned by PXP. |
sitestring (≤ 50 characters) required | Your unique site identifier, as assigned by PXP. |
If your request is successful, you'll receive a 200 response with the cached bank list. On a provider failure, the gateway may return the last known good cached list when one is available. A 500 response is returned when the cache is empty and the provider call also fails.
{
"banks": [
{
"code": "KTB",
"name": "Krung Thai Bank"
}
]
}| Parameter | Description |
|---|---|
banksarray required | The supported FlashFlow banks for your merchant and site. |
banks[].codestring required | The FlashFlow bank code (e.g., KTB). Use this value as fundingData.payByBank.bankName on create. |
banks[].namestring required | The display name of the bank. Don't send this as bankName on create. |
Use the following request to start a FlashFlow pay-in. Set apmProvider to Flashflow. Supply bankName with a bank code from the bank-list route, plus bankAccountNumber. Optionally set type (e.g., QR) and transactionTimeout in minutes. Render fundingData.payByBank.iframeSrc from the response in your own UI.
{
"merchant": "MERCHANT-1",
"site": "SITE-1",
"merchantTransactionId": "FLASHFLOW-TXN-001",
"merchantTransactionDate": "2026-09-21T10:00:00Z",
"transactionMethod": {
"intent": "Purchase",
"entryType": "Ecom",
"fundingType": "PayByBank"
},
"fundingData": {
"payByBank": {
"apmProvider": "Flashflow",
"bankName": "KTB",
"bankAccountNumber": "1234567890",
"type": "QR",
"transactionTimeout": 10
}
},
"amounts": {
"transaction": 100.00,
"currencyCode": "THB"
},
"shopper": {
"id": "Shopper_TH_01",
"firstName": "Somchai",
"lastName": "Jaidee",
"phoneNumber": "+66812345678",
"countryCode": "TH"
}
}| Parameter | Description |
|---|---|
merchantstring (≤ 10 characters) required | Your unique merchant identifier, as assigned by PXP. |
sitestring (≤ 50 characters) required | Your unique site identifier, as assigned by PXP. |
merchantTransactionIdstring (≤ 50 characters) required | A unique identifier for this transaction. |
merchantTransactionDatedate-time required | The date and time when the transaction happened, in ISO 8601 format. |
transactionMethodobject required | Details about the transaction method. |
transactionMethod.entryTypestring required | The entry type. For e-commerce FlashFlow transactions, this is always Ecom. |
transactionMethod.fundingTypestring required | The funding type. For FlashFlow, this is always PayByBank. |
transactionMethod.intentstring required | The payment intent. For a FlashFlow pay-in, set this to Purchase. Learn more about intents. |
amountsobject required | Details about the transaction amount. |
amounts.transactionnumber | The transaction amount. The numbers after the decimal will be zero padded if they are less than the expected currencyCode exponent. For example, GBP 1.1 = GBP 1.10, EUR 1 = EUR 1.00, or BHD 1.3 = 1.300. The transaction will be rejected if numbers after the decimal are greater than the expected currencyCode exponent (e.g., GBP 1.234), or if a decimal is supplied when the currencyCode exponent does not require it (e.g., JPY 1.0). For FlashFlow pay-ins, the minimum amount is 10 THB. |
amounts.currencyCodestring (1-3 characters) required | The currency code associated with the transaction, in ISO 4217 format. For FlashFlow, this must be THB. |
fundingDataobject required | Details about the payment method used for the transaction. For FlashFlow, use the Pay by bank funding shape only. |
fundingData.payByBankobject required | Pay-by-bank funding details for FlashFlow. |
fundingData.payByBank.apmProviderstring required | The alternative payment method (APM) provider. For FlashFlow, this must be Flashflow. |
fundingData.payByBank.bankNamestring required | The FlashFlow bank code from the bank-list route (e.g., KTB). Don't send the bank's display name. Treat as sensitive. |
fundingData.payByBank.bankAccountNumberstring required | The shopper source account number for the pay-in. Treat as sensitive. |
fundingData.payByBank.typestring | The FlashFlow pay-in type. For example QR. |
fundingData.payByBank.transactionTimeoutinteger (1-1440) | The pay-in timeout in minutes. When omitted, the provider default applies. Values below 10 are raised to a 10-minute floor before they are sent to FlashFlow. |
shopperobject required | Details about the shopper making the payment. Include id, firstName, lastName, and phoneNumber. Use id as your opaque shopper reference for later webhooks. |
shopper.countryCodestring (2 characters) | The shopper's country, in ISO 3166-1 alpha-2 format. When supplied, use TH. Omitting countryCode is accepted. |
shopper.phoneNumberstring | The shopper's phone number in E.164 format (e.g., +66812345678). |
If your request is successful, you'll receive a 200 response. For a successful FlashFlow purchase initiation, expect a PendingOnProvider state with fundingData.payByBank.iframeSrc for the QR or bank redirect surface. approvedAmount may also be present when FlashFlow returns a floating settlement amount. The response includes amounts, echoed from your request. There's no gatewayTokenId on the create response for pay-in. A payment account token is vaulted when the pay-in completes successfully and appears on the completion webhook and later query responses when stored.
The final outcome is delivered by a FlashFlow merchant webhook (e.g., flashflow-transaction-executed with state Authorised). See Webhooks below.
Always use the systemTransactionId for later PXP API calls against the same transaction. Provider payment identifiers are for reconciliation and support only.
{
"state": "PendingOnProvider",
"systemTransactionId": "1ed768bb-e88a-4636-91ae-67927ccbb02b",
"merchantTransactionId": "FLASHFLOW-TXN-001",
"merchantTransactionDate": "2026-09-21T10:00:00Z",
"providerTransactionId": "flashflow-ref-001",
"fundingData": {
"payByBank": {
"apmProvider": "Flashflow",
"iframeSrc": "https://pay.example/flashflow/qr/...",
"approvedAmount": 99.50
}
},
"amounts": {
"transaction": 100.00,
"currencyCode": "THB"
}
}FlashFlow doesn't support capture, void, or refund. Treat merchant webhooks as the authoritative final outcome for pay-ins and payouts.
Treat merchant webhooks as the authoritative final outcome. For reconciliation or a later status check, get the transaction details. For FlashFlow, pass systemTransactionId, fundingType set to PayByBank, and apmProvider set to Flashflow. FlashFlow queries return the last persisted state and don't call FlashFlow live.
Treat FlashFlow merchant webhooks as the authoritative final outcome for purchases and payouts. Don't treat the transaction initiation response alone as settlement, and don't treat the shopper finishing the iframeSrc surface as confirmation on its own. You don't receive raw FlashFlow callback bodies.
Use transactionMethod.intent to tell purchases and payouts apart when they share the same event code. shopperReference, gatewayTokenId, and transactionUpdateDatetime are omitted when not stored on the transaction. Bank account numbers and holder names are never included. On FlashFlow webhooks, transactionMethod.fundingType is delivered as PayByBanks (plural).
The following event codes apply to FlashFlow:
| Event code | State | Description |
|---|---|---|
flashflow-transaction-executed | Authorised | A FlashFlow purchase or payout completed successfully. |
flashflow-transaction-expired | Expired | A FlashFlow pay-in expired. |
flashflow-transaction-refused | Refused | A FlashFlow payout was refused. |
To learn how to set up and process webhooks, see Manage webhooks.
In your sandbox environment, you can use test bank codes instead of real ones to trigger a specific, predictable status on demand — without connecting to a real bank, moving any real money, or sending anything to FlashFlow's real systems. This allows you to test how your integration handles the statuses you can see in your webhook notifications and status responses:
- For pay-ins,
AuthorisedandExpired - For payouts,
Authorised,Error, andRefused
These test bank codes aren't available in production. If you submit one in that environment, it's treated as an unrecognised bank code and rejected the same way any other invalid bank code would be.
Use a test bank code exactly as you would use a real one: pass it as bankName in fundingData.payByBank when you create a payment or payout. No other part of your request changes.
You can also see all of the available test bank codes by calling Get FlashFlow supported banks API in a sandbox environment. They're automatically included in the list, so you can find them the same way you find a real bank. Some entries apply only to pay-ins, as described below.
The following table describes all of the test bank codes you can use and the corresponding outcome.
| Bank code | Description |
|---|---|
SIM-AUTHORISED | Pay-in or payout.
|
SIM-FLOATING | Pay-in only. Returns the simulator page with a randomly generated approvedAmount that differs from the requested amount. Stays PendingOnProvider until you choose Authorised or Expired on the test page. |
SIM-KYC | Pay-in only. Returns the simulator page with no approvedAmount (null or absent). Stays PendingOnProvider until you choose Authorised or Expired on the test page. |
SIM-ERROR | Payout only. Returns Error ~10 seconds after creation (provider status failed). |
SIM-REFUSED | Payout only. Returns Refused ~10 seconds after creation (provider status rejected). |
For pay-ins, use SIM-AUTHORISED, SIM-FLOATING, or SIM-KYC. Your response includes a normal iframeSrc redirect link, exactly like a real FlashFlow payment. Instead of FlashFlow's real hosted page, it opens a test page where you choose the outcome yourself.
The page shows two buttons: Authorised and Expired. Click whichever one you want to test. The payment stays PendingOnProvider until you click a button. There's no time limit and no auto-resolution.
Once you've clicked a button, your payment's status updates immediately to that same status, and your webhook notification fires with it. You can't change the status after that; create a new test payment to try a different one.
A payout has no page to open (a real FlashFlow payout doesn't return one either). Instead, about 10 seconds after you create it, your payout's status automatically updates to whichever status the bank code you chose maps to, and your webhook notification fires with that status.