RFP Testing
How to configure and test Instant Pay In (RfP) transactions in the Aeropay sandbox.
Overview
Request for Payment (RfP) depends on an action taken by the user inside their own banking app, so testing it in sandbox works differently than testing a standard ACH transaction.
In sandbox, Aeropay's partner bank simulates the RfP response. The outcome you receive is determined by the routing and account number on the bank account linked to your test user — each combination maps to a specific scenario (approved, rejected, expired, and so on). No real bank action is required.
For background on how RfP works and the full list of RfP webhook topics, see the Request for Payment Transaction guide.
Setup is required before you can test RfP. Contact your Aeropay representative to enable RfP in sandbox for your merchant account and to configure your test users.
1. Enable RfP for your sandbox merchant
Your Aeropay representative will enable Instant Pay In on your sandbox merchant account. Until this is done, transactions sent with rtp: true will fall back to ACH.
2. Set up your test users
Each scenario requires its own test user, because the scenario is determined by the bank account attached to that user.
Steps:
- Create a user for each scenario you plan to test using
POST /v2/user. - Provide the list of users to your Aeropay representative, along with the scenarios you want each one mapped to.
- Aeropay will set the routing and account numbers on each user's bank account to match the sandbox scenario.
Name your test users something that identifies the scenario (for example,
RfP Reject) so they're easy to keep straight once you start testing.
Available scenarios
| Scenario | Routing number | Account number | Description |
|---|---|---|---|
| Approved | 021214891 | 2955057589 | RfP is delivered to the user's bank and approved. |
| Rejected | 234567891 | 200000001 | RfP is delivered and the user declines it in their banking app. |
| Expired | 234567891 | 200000016 | RfP is delivered and the user takes no action. |
| Delivered only | 234567891 | 100000002 | RfP is delivered to the user's bank with no subsequent user action simulated. |
| Waterfall to ACH | coming | soon* | RfP eligibility check is not met; the transaction is processed as standard ACH instead. Triggered by the request itself rather than the bank account — see Choosing between RfP and ACH below. * Before we add an exception here, rely on testing with any other bank than above. |
Expiration timingThe RfP expiration window in Sandbox is 15 minutes. One significant difference in Staging is that notification of expiration is driven by an hourly process which notifies all of the RfP transactions that expired over the past hour. Depending on the timing of the generation of your
expiredRfP and the timing of the hourly process, it may take 15-95 minutes before your notification of expiration arrives.
3. Create an RfP transaction
Authenticate
Request a userForMerchant-scoped token for the test user you want to transact as:
POST /v2/token
{
"apiKey": "{{api_key}}",
"apiSecret": "{{api_secret}}",
"scope": "userForMerchant",
"id": "{{mainMerchantId}}",
"userId": "{USERID}"
}Pass the returned token as Authorization: Bearer {{token}} on the transaction call.
Create the transaction
Send POST /v2/transaction with rtp: true and a userIdentification object containing either an address or a birthday.
With address:
{
"merchantId": {{merchantId}},
"rtp": true,
"referenceId": "RfP testing - address",
"amount": {
"amount": 10,
"currency": "USD"
},
"userIdentification": {
"address": {
"streetName": "123 Main St",
"city": "Chicago",
"state": "IL",
"postalCode": "60601",
"country": "US"
}
}
}With birthday:
{
"merchantId": {{merchantId}},
"rtp": true,
"referenceId": "RfP testing - birthday",
"amount": {
"amount": 10,
"currency": "USD"
},
"userIdentification": {
"birthday": {
"date": "1990-11-10",
"country": "US",
"city": "Chicago"
}
}
}Choosing between RfP and ACH
Use the combinations below to test both paths, including the waterfall to ACH:
rtp | userIdentification | Result |
|---|---|---|
true | Valid (complete address or birthday) | Sent as RfP |
true | Incomplete or malformed | Waterfalls to ACH |
true | Omitted | Waterfalls to ACH |
false | Any | Processed as standard ACH |
| Omitted | Any | Processed as standard ACH |
When a transaction waterfalls to ACH, no RfP-specific webhooks fire. Your integration should not assume RfP was attempted based on the request alone — drive your UI from webhooks and the
isRtpflag.
4. Subscribe to webhooks
RfP webhooks are configured the same way as any other Aeropay webhook. Send a merchant-scoped POST /v2/webhook once per topic:
{
"topic": "transaction_rfp_delivered",
"url": "https://your-callback-url.com"
}Subscribe to both the RfP-specific topics and the standard transaction topics, since an RfP transaction can resolve through either. The full list of topics is documented in the Request for Payment Transaction guide, and general webhook setup is covered in the Webhooks guide.
Webhooks may arrive slightly out of order. Always use the most recent event for a given
transactionId, and make your handlers idempotent onidandtype.
TODO — webhook sequence per scenario. Add a table mapping each sandbox scenario to its expected webhook sequence once the ordering is confirmed. Blocked on open items Q1 and Q2 below.
5. Verify in the Merchant Portal
RfP transactions are marked with a lightning bolt icon in the sandbox Merchant Portal. Transactions processed over ACH — including those that waterfalled from RfP — appear without it.
TODO — screenshots. Add portal screenshots showing an RfP transaction in success, pending, and failed states, plus a standard ACH transaction for comparison.
Open items
Resolve these before publishing:
- Q1 —
transaction_completedtiming. Confirm whethertransaction_completedfires when the RfP is created, or only once funds have posted. Observed sandbox behavior suggests the former; the RfP guide documents the latter. If it fires at creation,transaction_rfp_initiatedis likely the correct topic and the RfP guide needs updating. - Q2 — rejected and expired sequences. Confirm the full ordering. Expected:
transaction_rfp_initiated→transaction_rfp_delivered→transaction_rfp_rejected/transaction_rfp_expired→transaction_voided. Observed sandbox behavior for reject skipstransaction_rfp_deliveredand returns a void only, which is being tracked as a defect. - Q3 — flow diagram. Publish the "RfP Payment Webhook Flow" chart once Q1 and Q2 are settled.
- Failed delivery scenario. No routing/account number identified yet. Confirm whether this is testable in sandbox today.
- Cancel scenario. Requires Aeropay-side interaction to trigger. Confirm whether it's exposed to merchants at all, or drop it from scope.
- Postman collection. Confirm whether the RfP scenarios collection will be shared externally, and link it here if so.
Updated about 4 hours ago

