Step 3: Payments
Available Corridors
To see which corridors have been activated for your team, use the GET corridors endpoint or see the team section of the Walapay dashboard.
When opening a new corridor, it is common for the first few payments to be checked by our banking partner's compliance team, which may delay these payments momentarily. This security audit is relaxed once these initial payments are validated and processed.
Types
There are 5 types of payments:
| Type | Definition |
|---|---|
| PAYIN | Funds are sent from an External Account to a Virtual Account (e.g., from an external bank account to a virtual bank account). Think of this as a deposit. |
| PAYOUT | Funds are sent from a Virtual Account to an External Account (e.g., from a virtual bank account to an external digital asset wallet). |
| INTERNAL | Funds are sent from a Virtual Account to another Virtual Account (e.g., from a virtual bank account to a virtual digital asset wallet). |
| EXTERNAL | Funds are sent from an External Account to another External Account (e.g., from an external bank account to an external digital asset wallet). |
| REFUND | Funds are being sent back in accordance to the refund logic described in the documentation below. |
Statuses
Payments of type PAYOUT, EXTERNAL, and INTERNAL can have the following statuses:

Two important notes:
- Completed status: If the payment is to a bank account, we do not have visibility passed the receiving bank accepting the funds. If a customer cannot see their funds for a completed payment, they should contact their bank to understand why the funds have not yet been credited to their account.
- Expired status: All payments created without a source.accountId in the payload will start with the AWAITING_FUNDS status. If the payment is not funded within 3 days of creation, it will be marked as EXPIRED (and any funds sent to it will expire). This is done for general housekeeping (so very old, unused payments do not stay open forever).
Funding
There are two ways payments can be funded. For detailed request/response examples of these two types of funding, visit the subpages (Fiat-to-Fiat, Fiat-to-Stablecoin, etc.).
With Source Account
The payment can include a source.accountId parameter in the payload that must be a virtual bank account or a virtual digital asset wallet. The starting status of a payment is PENDING, and the funds will be automatically pulled from this account. This scenario is best if you do not have your own banking or wallet provider.
Without Source Account
If the payment does not include a source.accountId, then the payment will have a starting status of AWAITING_FUNDS and the funds must be sent by the customer to the provided bank account or wallet address provided in the funding instructions object of the response. Note that payments created using this method will only be active for a short period of time (see quotes section below for more details). Exact cut offs can be found in the subpages (Fiat-to-Fiat, Fiat-to-Stablecoin, etc.)
FX
Source / Destination
By default, a payment guarantees a specific source and destination amount upon creation:
- If you create a payment with 100 USDC as the source.amount / source.currencyCode and PHP as the destination.currencyCode, the POST /payments response will include the destination.amount of PHP the beneficiary will receive: 5838
- If you instead create the payment with 5838 PHP as the destination.amount / destination.currencyCode, then the response will include 100 USDC as the source.amount and source.currencyCode
This allows you to know exactly how much will be required to send the payment and how much will arrive to the recipient. A limitation, however, is that you won't know what the source / destination amount pair will be until after you've created the payment. The solution is to create a quotes beforehand...
Quotes
If you need to be able to show the source and destination amount (and the exchange rate between the two currencies) to your user before the payment request is actually sent (e.g., they're on your app UI and want to know how much PHP they'll get if they send 100 USDC), include the createQuote parameter in the rate endpoint to receive a quoteId. Once a quote is created, you have 1 minute to include it in a POST /payments request (and it cannot be used for more than 1 payment).
Quotes cannot be used for payments that have a source currency of MXN.
Developer Fees
Developer Fees are only active for Stablecoin-to-Fiat and Stablecoin-to-Stablecoin payments.
To add your own fees on payments, you can use the developerFee object within the Payment payload. These fees will accumulate and can be sent to your account of choice (contact Walapay support to set this up) on a monthly basis.
This fee can be combination of a fixed amount and a variable percentage. Note that the fixed fee is always deducted before the variable fee is applied. Example: $1 Fixed with 0.01 variable fee will result in: (source.amount - 1) * (1 - 0.01), where the source.amount already includes the Walapay fees.
The fee is denominated in the source currency if that is a fiat currency, or in the fiat currency to which the source currency is pegged. If you are using a quote, the developer fee will be set to the quote's developer fee; you cannot set this field if you are using a quote.
Supporting Documents (Files)
Payments involving certain rails and currencies require supporting documents; this requirement comes from our underlying bank partners' policies and cannot be relaxed.
For the following rails and currencies, supporting documents are required and must be included in the "Files" field of a Payment:
- Global SWIFT (to any business or individual)
- China local USD / CNY
- HK local USD / CNH / HKD
- India using RDA rail (not VDA)
- Brazil using TED rail (B2B over 50,000 BRL only)
- Ghana local
Accepted Supporting Documents by common Payment Reason:
| Payment Reason | Supporting Document(s) |
|---|---|
| CONSULTING_FEES | Invoice1, contract, agreement between parties |
| DOWN_PAYMENTS_FOR_REAL_ESTATE | Purchase contract, mortgage contract |
| EMPLOYEE_SALARIES_OR_WAGES | Employment contract, pay-slip |
| EXPENSES_REIMBURSEMENT | Receipts, expense reports |
| PURCHASE_OF_GOODS | Invoice1, contract, agreement between parties |
| PURCHASE_OF_SERVICES | Invoice1, contract, agreement between parties |
| REMITTANCE | Bank statement, remittance confirmation letter2 |
| RENT | Rental agreement |
| ROYALTIES | Invoice1, royalty contracts |
- See below for best practices on submitting Invoices
- Remittance Confirmation Letter: please ensure to include the main purpose of the remittance (e.g. family support), the name of the sender and beneficiary, the amount, and the date.
Invoices Best Practices
To ensure consistent and reliable deliverability of Payments, we recommend the following best practices when submitting Invoices as Supporting Documents. Failure to adhere to these best practices may lead to RFIs, payment failure, or refunds.
- Invoices must clearly identify the buyer (sender) and seller (recipient) of the goods or services purchased. The full name and address of buyer and seller should be included, and the seller name should correspond to the name on the recipient bank account (ie. the External Account Holder Name).
- Invoice must be dated
- Invoice must contain the description and quantity of goods / services offered
- Invoice must be in the same amount and currency as the Payment amount / currency.
- Invoice should be signed and/or stamped by the relevant party
- Invoice should reasonably correspond to the Payment Reason
- If the recipient account number is included on the Invoice, it should correspond to the account number used in the Payment
RFIs
Certain payments may trigger a Request For Information (RFI), which is when the Walapay compliance team requires more information regarding a payment (this information is then passed on to the bank partner). An RFI can be sent while a payment is being processed or even after it has been completed (retroactive). Note that these RFIs will be sent to your team only, and you can then share these with your customer.
Answering these requests ASAP is critical. Failure to answer these RFIs may lead to the beneficiary being blocked for future payments (or your entire team being blocked from the bank partner if multiple RFIs are not answered).
Errors
When a payment fails, an error code will be provided in the payment object.
| Error Code | Definition |
|---|---|
| FUNDING_RECEIVED_AFTER_QUOTE_EXPIRED | Funds were received after the FX quote expired, so the rate is no longer valid and the transfer cannot be processed. |
| AMOUNT_TOO_LOW_FOR_CURRENCY_PAIR_AND_RAIL | The transfer amount is below the minimum allowed for the specified currency pair and payment rail. |
| AMOUNT_TOO_HIGH_FOR_CURRENCY_PAIR_AND_RAIL | The transfer amount exceeds the maximum allowed for the specified currency pair and payment rail. |
| INVALID_EXTERNAL_ACCOUNT_DETAILS | The provided beneficiary account details are invalid. Therefore, the beneficiary bank could not credit the funds. This error is given if the bank does not specify what exactly is incorrect. |
| INVALID_EXTERNAL_ACCOUNT_NUMBER | The beneficiary account number is invalid or incorrectly formatted. |
| INVALID_EXTERNAL_ACCOUNT_HOLDER_NAME | The beneficiary account holder name is invalid, missing, or does not meet validation requirements. |
| INVALID_EXTERNAL_ACCOUNT_HOLDER_ADDRESS | The beneficiary account holder address is invalid, incomplete, or improperly formatted. |
| FUNDS_RETURNED_BY_RECEIVING_BANK | The receiving bank rejected the transfer and returned the funds. |
| EXTERNAL_ACCOUNT_DEPOSIT_LIMIT_EXCEEDED | The beneficiary account has exceeded its allowed deposit or incoming transfer limits. |
| EXTERNAL_ACCOUNT_HOLDER_ADDRESS_IS_PMB_OR_PO_BOX | The provided address is a PO Box or PMB, which is not accepted for compliance reasons. |
| RFI_NOT_ANSWERED_IN_TIME | A Request for Information (RFI) was not responded to within the required timeframe, causing the transfer to fail. |
| BLOCKED_BY_COMPLIANCE | The transaction was blocked due to compliance, regulatory, or risk checks. |
| RETURNED_AT_BENEFICIARY_REQUEST | The beneficiary requested the return of funds after the transfer was completed. |
| INVALID_ROUTING_CODE | The provided routing code (e.g., sort code, ABA, IFSC) is invalid or does not match the bank details. |
| BLOCKED_BY_INTERMEDIARY_BANK | An intermediary (correspondent) bank blocked or rejected the transaction during processing. |
Sandbox Behavior
- Payments sent in Sandbox will not actually send to the intended account; the status will go straight to PROCESSING for payments with source.accountId and remain at AWAITING_FUNDS for payments without a source.accountId
- The source.accountId's fundingInstructions is dummy data. Do not send any funds to the bank or wallet address provided
- The exchange rates you see in Sandbox may be different than Production
