Skip to content

FlashFlow transaction

Get a list of supported FlashFlow banks, then process online FlashFlow purchases and payouts using Pay by Bank.

Overview

You can submit a FlashFlow transaction in these ways:

  • Purchase (pay-in): Create a pay-by-bank transaction with apmProvider set to Flashflow and intent set to Purchase. Supply bankName (the bank code from the bank-list route) and bankAccountNumber. Render fundingData.payByBank.iframeSrc from 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 intent set to Payout and supply all three of bankName, bankAccountNumber, and bankAccountHolderName. Don't also send gatewayTokenId. Capture fundingData.payByBank.gatewayTokenId from the response to reuse the destination later.
  • Payout (withdrawal), stored bank account: Create a payout and supply gatewayTokenId from 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.

Get FlashFlow supported banks

GET
/v1/altp-flashflow-processor/{merchant}/{site}/bank-list

Request example

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'
ParameterDescription
merchant
string (≤ 10 characters)
required
Your unique merchant identifier, as assigned by PXP.
site
string (≤ 50 characters)
required
Your unique site identifier, as assigned by PXP.

Response example

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"
    }
  ]
}
ParameterDescription
banks
array
required
The supported FlashFlow banks for your merchant and site.
banks[].code
string
required
The FlashFlow bank code (e.g., KTB). Use this value as fundingData.payByBank.bankName on create.
banks[].name
string
required
The display name of the bank. Don't send this as bankName on create.

Initiate a FlashFlow transaction

POST
/v1/transactions

Request examples

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
merchant
string (≤ 10 characters)
required
Your unique merchant identifier, as assigned by PXP.
site
string (≤ 50 characters)
required
Your unique site identifier, as assigned by PXP.
merchantTransactionId
string (≤ 50 characters)
required
A unique identifier for this transaction.
merchantTransactionDate
date-time
required
The date and time when the transaction happened, in ISO 8601 format.
transactionMethod
object
required
Details about the transaction method.
transactionMethod.entryType
string
required
The entry type. For e-commerce FlashFlow transactions, this is always Ecom.
transactionMethod.fundingType
string
required
The funding type. For FlashFlow, this is always PayByBank.
transactionMethod.intent
string
required
The payment intent. For a FlashFlow pay-in, set this to Purchase. Learn more about intents.
amounts
object
required
Details about the transaction amount.
amounts.transaction
number
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.currencyCode
string (1-3 characters)
required
The currency code associated with the transaction, in ISO 4217 format. For FlashFlow, this must be THB.
fundingData
object
required
Details about the payment method used for the transaction. For FlashFlow, use the Pay by bank funding shape only.
fundingData.payByBank
object
required
Pay-by-bank funding details for FlashFlow.
fundingData.payByBank.apmProvider
string
required
The alternative payment method (APM) provider. For FlashFlow, this must be Flashflow.
fundingData.payByBank.bankName
string
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.bankAccountNumber
string
required
The shopper source account number for the pay-in. Treat as sensitive.
fundingData.payByBank.type
string
The FlashFlow pay-in type. For example QR.
fundingData.payByBank.transactionTimeout
integer (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.
shopper
object
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.countryCode
string (2 characters)
The shopper's country, in ISO 3166-1 alpha-2 format. When supplied, use TH. Omitting countryCode is accepted.
shopper.phoneNumber
string
The shopper's phone number in E.164 format (e.g., +66812345678).

Response examples

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.

Query a FlashFlow transaction

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.

Webhooks

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 StateDescription
flashflow-transaction-executedAuthorisedA FlashFlow purchase or payout completed successfully.
flashflow-transaction-expiredExpiredA FlashFlow pay-in expired.
flashflow-transaction-refusedRefusedA FlashFlow payout was refused.

Examples

A successful FlashFlow purchase (Purchase) or payout (Payout) uses flashflow-transaction-executed with state Authorised. A successful pay-in may include gatewayTokenId when a payment account token has been vaulted.

Purchase:

{ "eventDate": "2026-09-21T10:30:00.0000000Z", "eventCategory": "transaction", "eventOwner": { "merchantGroup": "merchant-group-1", "merchant": "MERCHANT-1", "site": "SITE-1" }, "eventData": { "eventCode": "flashflow-transaction-executed", "state": "Authorised", "stateData": { "code": "APM001", "message": "Payment executed" }, "amounts": { "transaction": 99.5, "currencyCode": "THB" }, "merchant": "MERCHANT-1", "site": "SITE-1", "shopperReference": "Shopper_TH_01", "gatewayTokenId": "b6e2f1a4-c3d8-4f7a-b1e9-d2c3f4a5b6c7", "transactionUpdateDatetime": "2026-09-21T10:30:00Z", "transactionMethod": { "intent": "Purchase", "entryType": "Ecom", "fundingType": "PayByBanks" }, "fundingData": { "payByBank": { … } }, "providerResponse": { "provider": "Flashflow", "providerTransactionId": "flashflow-ref-001", "providerTransactionStatus": "completed", "providerResponseCode": "completed", "providerResponseMessage": "Payment executed" }, "merchantTransactionId": "FLASHFLOW-TXN-001", "systemTransactionId": "1ed768bb-e88a-4636-91ae-67927ccbb02b" } }

Payout:

{ "eventDate": "2026-09-21T11:00:00.0000000Z", "eventCategory": "transaction", "eventOwner": { "merchantGroup": "merchant-group-1", "merchant": "MERCHANT-1", "site": "SITE-1" }, "eventData": { "eventCode": "flashflow-transaction-executed", "state": "Authorised", "stateData": { "code": "APM001", "message": "Payment executed" }, "amounts": { "transaction": 100, "currencyCode": "THB" }, "merchant": "MERCHANT-1", "site": "SITE-1", "gatewayTokenId": "b6e2f1a4-c3d8-4f7a-b1e9-d2c3f4a5b6c7", "transactionUpdateDatetime": "2026-09-21T11:00:00Z", "transactionMethod": { "intent": "Payout", "entryType": "Ecom", "fundingType": "PayByBanks" }, "fundingData": { "payByBank": { … } }, "providerResponse": { "provider": "Flashflow", "providerTransactionId": "flashflow-ref-002", "providerTransactionStatus": "completed", "providerResponseCode": "completed", "providerResponseMessage": "Payment executed" }, "merchantTransactionId": "FLASHFLOW-PAYOUT-001", "systemTransactionId": "2fd879cc-f99b-4747-92bf-78038ddcc03c" } }

To learn how to set up and process webhooks, see Manage webhooks.

Testing

How it works

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, Authorised and Expired
  • For payouts, Authorised, Error, and Refused

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.

Available test bank codes

The following table describes all of the test bank codes you can use and the corresponding outcome.

Bank code Description
SIM-AUTHORISEDPay-in or payout.
  • For pay-ins:
    • Returns the simulator page.
    • approvedAmount matches the requested amount.
    • Stays PendingOnProvider until you choose Authorised or Expired on the test page.
  • For payouts: Returns Authorised ~10 seconds after creation (provider status completed).
SIM-FLOATINGPay-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-KYCPay-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-ERRORPayout only. Returns Error ~10 seconds after creation (provider status failed).
SIM-REFUSEDPayout only. Returns Refused ~10 seconds after creation (provider status rejected).

What happens after

Payment (pay-in) creation

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.

Payout creation

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.