RFP Testing

How to configure and test Instant Pay In (RfP) transactions in the Aeropay sandbox.

🚧

Under Construction

Additional improvements to testing are continuing to be made

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:

  1. Create a user for each scenario you plan to test using POST /v2/user.
  2. Provide the list of users to your Aeropay representative, along with the scenarios you want each one mapped to.
  3. 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

ScenarioRouting numberAccount numberDescription
Approved0212148912955057589RfP is delivered to the user's bank and approved.
Rejected234567891200000001RfP is delivered and the user declines it in their banking app.
Expired234567891200000016RfP is delivered and the user takes no action.
Delivered only234567891100000002RfP is delivered to the user's bank with no subsequent user action simulated.
Waterfall to ACHcoming 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.
📘

Remember

These routing and account numbers are valid in the sandbox environment only.

⏱️

Expiration timing

The 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 expired RfP 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:

rtpuserIdentificationResult
trueValid (complete address or birthday)Sent as RfP
trueIncomplete or malformedWaterfalls to ACH
trueOmittedWaterfalls to ACH
falseAnyProcessed as standard ACH
OmittedAnyProcessed 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 isRtp flag.


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 on id and type.

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_completed timing. Confirm whether transaction_completed fires 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_initiated is 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 skips transaction_rfp_delivered and 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.

Did this page help you?