End-to-End Testing in the MT Sandbox

A practical overview of how to test common Modern Treasury integrations in the sandbox before moving to production

This guide outlines a basic approach to testing the Modern Treasury (MT) product suite in your MT sandbox environment. Each section focuses on a core area of MT that is commonly integrated with client-side workflows.

Testing Methodology

For effective sandbox testing, follow these three phases for each of the core product areas listed in this guide:

1. API Testing

Test the Modern Treasury API independent of any application-side testing. In this phase, the relevant MT API endpoints and events/webhooks for a given section should be reviewed and tested to validate their behavior.

API tests should:

2. Unit Testing

Test your application independent of the MT API or other external services. Use mock MT API responses to test units of code in your application to confirm proper execution of workflows relevant to the given section.

3. Integration Testing

Once both sides of the integration have been tested independently, test both the MT API and your application together.

MT API requests are typically synchronous, but many end-to-end workflows are event-driven and time-delayed. Integration tests should:

  • wait for any relevant webhook(s) or poll for a terminal state rather than asserting immediately
  • verify each end-to-end workflow for a given section, ensuring your application is correctly sending API calls and handling events
  • ensure accurate data transmission between systems

Segment your tests appropriately and, at minimum, include idempotency keys so reruns in Continuous Integration systems don’t create duplicates.

Collectively, the sections in this guide will facilitate end-to-end testing in the sandbox before promoting to the Modern Treasury production environment.

Using the Modern Treasury Sandbox

Use Modern Treasury's sandbox mode when testing your use-case via UI or API:

  • UI: In your Modern Treasury organization, enable the “View Sandbox” toggle in the left-side menu. When in sandbox mode, the top-left corner of the screen will indicate “Viewing sandbox.”
  • API Key: While in sandbox mode in the UI, navigate to the API Keys page and use the default sandbox API key or create new ones as needed. API keys generated in sandbox mode will only apply to the sandbox. Sandbox API keys start with test.

Your organization’s Organization ID is found on the General Settings page and is always used as the username in the basic authentication of API requests. The API key is the password.

📘

Most actions available via the Modern Treasury API can also be performed via the UI. This guide focuses on the API but mentions UI options where commonly used in particular workflows. If you plan to use the UI for other workflows, make sure to consider the UI testing steps required for your use case.

Internal Accounts

Internal Accounts (IA) are the bank accounts owned by your organization that you will be moving money from/to. In production, MT will onboard these accounts. In the sandbox, use the default sandbox IAs, or create additional IAs as needed.

The default sandbox IAs belong to the following sandbox banks:

  • Gringotts Wizarding Bank (GWB): Payment objects, like Payment Orders, that originate from GWB accounts automatically generate Transactions for reconciliation to simulate production activity.
  • The Iron Bank of Braavos (IBB): Payment objects that originate from IBB accounts do not automatically generate Transactions. This is helpful when it is not desirable to have the sandbox simulate activity. For Expected Payment reconciliation testing, you may prefer manually generating Transactions to test Reconciliation Rules.

IAs can be found on the accounts page in your MT sandbox or via the List Internal Accounts endpoint. This guide will note which sandbox bank should be used for a given operation.

Differences from Production

Since the sandbox is a simulated environment intended for testing, its behavior can differ from that of the production environment. Here are some key differences:

  • Most MT objects have a live_mode boolean field. This will be false for sandbox objects and true for production objects.
  • Auto-generated GWB transactions reconcile within ~5 minutes in sandbox vs. minutes to days in production depending on the payment rail and bank.
  • Only ACH, wire, book transfer, check, and RTP payment types are simulated for GWB sandbox IAs.
  • In Sandbox, the default rate limit is 25 requests per second, whereas in production the limit is 100. We do not recommend running load tests in the sandbox as sandbox performance will not accurately reflect production performance. For general performance recommendations, see this article.

Metadata in Modern Treasury

Most MT objects support the use of metadata. Metadata is an optional but useful key-value map for additional details MT does not model natively.

Some common uses include:

  • useful descriptive info
  • categorization fields for querying (e.g. deal_type, transaction_type, or customer_type)
  • internal IDs (e.g. user_id or invoice_id)
  • general ledger reporting tags for downstream ERP journal entries (e.g. gl_code)

An object's metadata is always included within the object’s JSON response when it is received from MT via API or webhook. Metadata can also be queried directly via the “list” endpoints, such as List Payment Orders.

Include specific metadata, if relevant, to your core objects as part of the testing process.

Counterparties and External Accounts

Counterparty objects in MT represent entities that you send money to or receive money from. A single Counterparty can have many External Accounts (EA). EAs represent the actual bank accounts belonging to the Counterparty. EAs are the receiving accounts used when creating a Payment Order.

Account Collection

Determine which account collection method to use when onboarding Counterparties and collecting their bank account details:

  • Pre-Built UIs: These options allow MT to collect a Counterparty’s bank account info without your organization having to directly handle sensitive account information. You will first need to create the Counterparty object with at least a name before using these options to collect the Counterparty’s EA details:
    • Embedded Form - an MT-hosted form embedded into your application to collect EA info for a counterparty.
    • Counterparty Invite - emails a link to an MT-hosted webpage to collect EA info for a counterparty.
  • Plaid Integration: The MT Plaid integration lets your organization use Plaid to verify a bank account and pass its details to MT without directly handling sensitive info. Please note that Plaid is an independent platform with its own fees.
  • API: Using the API gives the most control and flexibility over the Counterparty and EA onboarding flows, if your organization is fine with handling the sensitive bank account info directly:
    • Create Counterparty Endpoint - Your organization collects the needed info and creates the Counterparty and EA in a single call.
    • Alternatively, the Counterparty can be created separately from the External Account. The Create EA endpoint can be used to add the EA details to a counterparty at a later time. This multi-step pattern is typical for progressive onboardings.
  • Bulk CSV: A large number of Counterparties can be created at once by uploading a CSV file in the MT UI. This bulk Counterparty upload is useful for migrating existing bank account details from another platform into MT.

The bank account details that need to be collected will vary based on the location of the recipient’s bank. Consider where your organization’s Counterparties will be located and ensure the correct info is requested for the relevant location and payment type. See the following for more info:

The chosen account collection method will determine how your organization monitors for the creation of the relevant objects:

  • Pre-Built UIs: listen for the created EA webhook and store the id client side for quick retrieval later when programmatically sending Payment Orders to the EA. The Counterparty id should also be stored client side when being created via the Create Counterparty Endpoint, unless external_id is being used instead.
  • API: upon successful completion, API requests will return the object data in JSON format. Store the id of the EA on the client side for quick retrieval later when programmatically sending Payment Orders to the EA. The id of the Counterparty should also be stored, unless external_id is being used instead.

Testing Notes

As part of the testing process for this section, ensure that:

  1. The desired flow is collecting the appropriate details.
  2. The resulting Counterparty and EA objects are being created as expected in MT.
  3. Object data, such as each object id, is being stored client side for later retrieval.

Payment Orders

Payment Orders (PO) are instructions to move money between an Internal Account (IA) and an External Account (EA) or between an IA and another IA.

For testing purposes, enable sandbox simulation of the client-side workflows that will trigger Payment Order creation in production. These workflows should be repeatable and represent the actual workflows that will take place within your organization’s application.

When triggering the creation of a PO in the workflow:

  1. Use the Create Payment Order endpoint.
  2. Fill in the required fields:
    1. type

    2. amount

    3. direction

    4. originating_account_id: in the sandbox, use the id of one or your Gringotts Wizarding Bank (GWB) IAs.

    5. One of either receiving_account_id or receiving_account

      Note: since the EA should have already been onboarded with its id stored client side, receiving_account_id would be the appropriate field to use.

    6. external_id (optional): recommended if client-side events that trigger POs have their own UUIDs. The external_id field allows you to directly associate the event with the resulting PO using your organization’s own UUIDs.

  3. Use other fields as needed.
🚧

The required fields are the bare minimum needed to create POs. Other fields may be needed depending on the particular use case, rail, or bank.

Some fields may not behave in the sandbox as they would in production. For example, the process_after field will cause an error for all Iron Bank of Braavos accounts, since there is no simulated processing activity in the sandbox for these accounts. In some cases, the exact behavior for certain PO use cases may only be achievable in production.

Once a PO request has been successfully submitted, the GWB sandbox IAs will automatically generate a Transaction object and reconcile the PO to the Transaction within ~5 minutes. This simulates a successful PO lifecycle. Please note that, in production, the time taken to receive the Transaction from the bank and reconcile it to the PO will vary by bank and/or payment rail.

Payment Order Webhooks

Modern Treasury transmits lifecycle webhooks for Payment Orders (POs). As the PO moves through its lifecycle, certain PO webhooks may be useful to trigger downstream client-side actions. The most common of these are:

  • completed, which indicates the originating bank (i.e. the IA) has successfully executed the PO.
  • reconciled, which indicates MT has reconciled the PO with its posted transaction.

Examples of downstream actions that might be executed upon receiving the completed or reconciled webhooks include updating a customer’s in-app balance or status. Since the PO will need to be matched on the client side for downstream actions, store the PO’s id from the Create PO endpoint. If using external_id, you can match on that as well.

Account for other statuses and/or webhooks based on your use-case and required client-side workflows. A list of statuses can be viewed on this page, and webhook events can be viewed on this page.

To test other PO statuses, the MT sandbox has special default counterparties that will automatically simulate certain paths when POs are sent to the EAs belonging to these counterparties. For example, this page explains how return simulation works.

💡

If using MT's Solution Architecture service, your assigned team member can help identify the statuses relevant to your use case and the needed workflows to support them.

Testing Notes

As part of the testing process for this section, ensure that:

  1. POs are being successfully created in MT with the expected details.
  2. Each PO id (or external_id) is stored client side.
  3. Required webhooks are being received and downstream actions are being executed as expected.

Expected Payments

Expected Payments (EP) represent payment activity that occurs outside of Modern Treasury. They represent payment objects that can be automatically or manually reconciled to bank Transactions, just like Payment Orders (PO).

Payment Orders (PO) are the primary payment objects in MT, but only represent payments that were originated via MT. Payments originated outside of MT or received into the bank account will still have their resulting Transactions imported from the bank. You can reconcile these Transactions with Expected Payments.

There are two common scenarios where EPs are used:

  • Incoming payments to your organization that were originated by the sender
  • Payments your organization originated outside of MT, such as via an online bank portal

Reconciliation Rules

Since these payments originate outside of MT, you must define both the EP objects and the Reconciliation Rules that determine how the EPs get reconciled to their matching Transactions.

Reconciliation Rules govern the automated reconciliation between EPs and Transactions. Reconciliation Rules use the reconciliation_rule_variables defined on the EP object to match EPs to the correct Transactions.

See the following documentation to learn more about how these work:

To test EP workflows in the sandbox, you must:

  1. Identify which of your workflows will result in non-MT payment activity.
  2. Data Map: Determine what data from your internal systems can be mapped to reconciliation_rule_variables so they can be matched to the Transactions that will be received from the bank.
  3. Create Rules: Configure a hierarchy of Reconciliation Rules that will match the EPs to their Transactions. Rules execute in top-down, waterfall order. The most specific rules (matching on fields like date ranges, specific filters, and/or using one-to-one matching strategies) should be placed first. The least specific rules (broader strategies, no dates, etc.) should be placed later.

Below is a simple example of an EP testing workflow. For the API calls below, make sure the internal_account_id being used belongs to one of the “Iron Bank of Braavos” accounts (the bank account will have “IBB” in front of its name):

  1. Configure the Reconciliation Rule(s) needed to test the current unoriginated payment workflow.

  2. Use the Create Expected Payment endpoint to create EPs. Set the reconciliation_rule_variables with values that are expected to match the Transaction so the Reconciliation Rules can auto-reconcile them.

  3. Use the Create Transaction endpoint to manually create Transactions that match the EP(s).

📘

Here, we must manually or programmatically generate Transactions in sandbox to simulate automatic Transaction generation in production.

Typically, this is performed by:

  1. Replicating your Internal Account setup in sandbox.
  2. Exporting Transactions from production by running List Transactions with a production API key.
  3. Re-creating those Transactions in sandbox by running Create Transaction to mirror production activity within your sandbox-mirrored Internal Accounts.

Note: Certain Transaction data received from banks, such as the vendor_description present in Transactions, can vary between banks. For accurate EP testing in the sandbox, you should ensure the sandbox Transactions accurately represent what is expected in production.

  1. Let the Reconciliation Rules auto-reconcile the EPs to the Transactions. Reconciliation should run and complete within minutes of Transaction creation.

  2. Repeat to test all unoriginated payment workflows.

Expected Payments Webhooks

EPs have their own lifecycle that causes them to move through different states, similar to Payment Orders. To see the different states and their corresponding events/webhooks, see this page.

💡

If using MT's Solution Architecture service, your assigned team member will be able to assist with data mapping and defining your reconciliation_rule_variables, configuring your Reconciliation Rules, and testing EPs and their webhooks accurately and at scale in the sandbox to support your use cases.

Testing Notes

As part of the testing process for this section, ensure that:

  1. EPs are being created as expected in MT.
  2. Each EP id (or external_id) is stored client side upon creation.
  3. Reconciliation Rules are reconciling the EPs to transactions as expected.
  4. Required webhooks are being received and downstream actions are being executed as expected.

Ledgers

MT Ledgers is a double-entry ledger that records transactions and tracks balances in real time as actions are being executed in your organization’s application. There are four core objects that make up the MT Ledger:

Ledgers can be implemented independently of any other MT products. You can have many Ledgers as well - a Ledger and its contained objects, can exist separately of one another as well. This makes Ledgers easy to test: you can spin up a new Ledger at any time for each fresh test, or you can test your workflows within a single Ledger with clear naming.

To test Ledgers, you will first need to consider all workflows that involve Ledger Accounts (LA), Ledger Account Categories (LAC), and Ledger Transactions (LT). Some examples of typical ledger designs for common use cases can be found in our Ledgers Tutorials.

Ledger Accounts

Ledger Accounts (LA) represent the discrete balances that your organization needs to track in its Ledger. They are organized into a Chart of Accounts (COA), which details all the different LAs that need to be represented in the Ledger. See our Accounting for Developers series for examples of COAs.

💡

If you're using MT's Solution Architecture service to help design your Ledger, the COA will be in the Solution Document provided by your assigned team member. The accounts will also be referenced in the provided T-Account.

To create LAs:

  1. Use the Create Ledger Account endpoint.
  2. Fill in the required fields:
    1. name: Any descriptive name your organization will recognize.
    2. currency: an ISO 4217 currency name. See this article for more on LA currencies.
    3. normal_balance: either debit or credit. See this article for more on account normality.
    4. ledger_id: the id of the Ledger to which this LA belongs.
    5. metadata (optional): include any additional info as metadata.
    6. ledger_account_category_ids (optional): include the id of any Ledger Account Categories to which this LA should be added upon creation.
    7. external_id (optional): recommended if you have a client-side object UUID that should be directly tied to this LA object.
  3. Use other fields as needed.

Ledger Account Categories

Ledger Account Categories (LAC) group LAs and aggregate their balances.

Your workflows may require native aggregation to support critical path queries (to power a UI, for example). Identify your critical LACs during the design phase and test their creation before moving to production. However, LACs can be created or destroyed at any time, so it’s not necessary to know or create every LAC from the beginning.

To create LACs:

  1. Use the Create Ledger Account Category endpoint.
  2. Fill in the required fields:
    1. name: Any descriptive name your organization will recognize.
    2. normal_balance: either debit or credit. This is used to determine how LAs in the LAC impact its balance. For example, if the value is debit, debit-normal LAs will increase the LAC balance and credit-normal LAs will decrease it. See this article for more on normality.
    3. currency: an ISO 4217 currency name. All LAs in this LAC must have the same currency.
    4. ledger_id: the id of the Ledger to which this LAC belongs.
    5. metadata (optional): include any additional info as metadata.
    6. ledger_account_category_ids (optional): if this LAC should be part of other LACs upon creation, include the id of any LACs here.
    7. external_id (optional): recommended if there is a client-side object UUID that should be directly tied to this LAC object.
  3. All other fields are optional . Some, like description, can be used as needed.
💡

If using MT's Solution Architecture service to help design your Ledger, your Solution Document will include guidance on both LA and LAC design.

Ledger Transactions

Ledger Transactions (LT) contain the Ledger Entries that modify the LA balances. Most LTs resulting from these workflows will fall into one of two categories:

  • standalone LT
  • embedded LT

Standalone Ledger Transactions

Some workflows will require writing LTs independently of creating any other objects in MT. These are typically the simplest to begin testing with as they only require the creation of the LT:

  1. Use the Create Ledger Transaction endpoint
  2. Fill in the required fields:
    1. status: defaults to pending but can be set to posted. The status impacts the LA balances. The desired status will depend on what’s required by the workflow, but a general rule of thumb is:
      1. pending is often used when real money movement is involved, as the LT shouldn’t be considered posted until funds have settled. Once funds are settled, the LT is updated to posted.
      2. posted is often used when a LT is not tied to real-world money movement and exists on the ledger only to adjust LA balances.
    2. ledger_entries:
      1. amount: set the amount for the particular Ledger Entry (LE). The sum of all credit LEs must match the sum of all debit LEs within a Ledger Transaction.
      2. direction: either debit or credit and determines if the LE increases or decreases the LA balance based on its normality. See this article for additional details on debits and credits with respect to normality.
      3. ledger_account_id: the id of the LA to which this entry should be applied.
    3. external_id (optional): recommended if client-side events that trigger LTs have their own UUIDs. The external_id field allows you to directly associate the event with the resulting LT using your organization’s own UUIDs.
  3. Use other fields as needed.

Embedded Ledger Transactions

LTs can be linked to Payment Orders or Expected Payments so that the LT’s status is automatically updated based on the status of the payment object:

The most common pattern for linking LTs is to create the payment object and LT in a single, atomic API call. LTs created in this way are referred to as “embedded LTs”.

In both the Create Payment Order and Create Expected Payment endpoints, the LT can be embedded using the ledger_transaction field.

Alternatively, you can create the Ledger Transaction asynchronously and reference the payment object by utilizing the ledgerable_type and ledgerable_id fields.

Ledger Account Locking

You may want to use balance locking or version locking to enforce balance preconditions on Ledger Accounts (e.g. ensuring a balance will not go negative to avoid processing a Ledger Transaction if the Ledger Account does not have the needed funds).

Confirm which workflows will require locking so these can be accounted for in testing. Note that locking has its own rate limits. For additional considerations when designing for concurrency, see our article Design a Ledger for Concurrency.

💡 If using MT's Solution Architecture service to help design your Ledger, your organization’s workflows should be reflected in the T-Account provided by your assigned team member.

Ledger Webhooks

Ledger Account Webhooks

LAs have two events: created and updated. These events' webhooks can be monitored as needed to support specific workflows, such as monitoring for updates to certain LAs.

Ledger Transaction Webhooks

LTs have three events that will trigger webhooks. These can be triggered by actions via the API or UI, but are also triggered by automated actions taken by MT:

  • updating status to posted when embedded LTs are being used
  • creating Ledger Transaction Reversals automatically when processing Returns
  • etc.

Testing Notes

As part of the testing process for this section, ensure that:

  1. All Ledger objects are being created in the correct Ledger.
  2. The correct sets of LAs and LACs are being created as needed.
  3. LTs write the correct entries to the correct LAs for all workflows.
  4. LA and LAC balances accurately reflect expected results.
  5. The id of LAs, LTs, and LACs are being stored upon creation on the application side as needed for quick reference later, unless external_id is being used instead.
  6. Required webhooks are being successfully received and downstream actions are being executed as expected.

Virtual Accounts & Incoming Payment Details

Some banks offer virtual accounts, which are "subaccounts" linked to a standard bank account. These virtual accounts serve as unique account numbers that can receive incoming payments, and some virtual accounts can originate payments and report their own balances.

There are two types of virtual account products supported by banks and available in Modern Treasury:

  • Virtual Accounts (colloquially: "naive" virtual accounts): receive-only subaccounts that have a unique account number for incoming payments.
  • Nested Internal Accounts (colloquially: "smart" virtual accounts): bank-ledgered subaccounts that have a unique account number for incoming payments and can originate payments and hold a balance natively at the bank.

If you have a virtual account product enabled at your banking partner, please consider the workflows that involve creating Virtual Accounts, Nested Internal Accounts, and/or receiving Incoming Payment Details to simulate this activity in the sandbox by combining the following topics.

Virtual Accounts

Virtual Accounts (VA) are bank-issued alias account numbers (aka "subaccounts") that route to the same central bank account (e.g. a For Benefit Of (FBO) account). The VA object can be used to represent each alias and attribute inbound payment activity in MT.

Use VAs for workflows where your application needs to allocate a new inbound account number per customer, entity, or business concept (i.e. a VA per loan).

Any time a new VA number needs to be used by your organization, use the Create Virtual Account endpoint to create a VA object in MT associated with that VA number:

  • name: the name of the entity this VA represents.
  • internal_account_id: the id of the Internal Account (IA) for which this VA is a subaccount. In the sandbox, this should be the ID of one of the Gringotts Wizarding Bank accounts.
  • account_details:
    • account_number (optional): if applicable, the account number this VA should be assigned. For most banks, this is typically optional as MT will dynamically assign VA numbers based on a range or pattern provided by the bank. In the sandbox, VA numbers are dynamically generated, so leave this field blank.

For downstream workflows, store:

  • VA account_number: if dynamically generated by MT, store it client side and/or provide to the counterparty who will be sending payments to the VA.
  • VA id: for quick retrieval and linking.

Nested Internal Accounts

Nested Internal Accounts (NIA) are “ledgered” virtual accounts i.e. subaccounts have their own balances and may support additional functionality. In these cases, you should model the bank’s subaccounts in MT as Nested Internal Accounts rather than Virtual Accounts .

Before creating Nested Internal Accounts, ensure you have:

  • A parent Internal Account (the real bank account you’ll nest under)
  • A connection_id for the bank connection (provided by MT)

Create NIAs via the standard Create Internal Account endpoint, specifying the parent_account_id of the parent IA .

Required fields will vary by bank configuration, but at minimum you should expect to provide:

  • connection_id
  • name
  • party_name
  • currency
  • parent_account_id

If you’re holding funds on behalf of an entity (or want to attribute a set of transactions to them), you can link the nested IA to a Counterparty using counterparty_id on creation .

For downstream workflows, store:

  • the NIA id (for retrieval and linking)
  • the nested IA account_details / routing_details (to provide payment instructions to originators)

Incoming Payment Details

Incoming Payment Details (IPD) are a type of payment object that represent unoriginated, incoming payments. When available at the bank, MT creates IPDs automatically and reconciles them to pending and posted Transactions from the bank, updating their status to tentatively_reconciled or completed, respectively.

IPDs are often generated from specialized bank reporting, like raw Fedwire files for wire IPDs or NACHA received files for ach IPDs, and as a result, they can serve as an early notification of received funds.

IPDs are required for Virtual Accounts ("naive") and helpful for Nested Internal Accounts ("smart"). When used alongside VAs, IPDs allow MT to automatically attribute inbound payments to their corresponding VAs.

Though IPD creation happens automatically in production, IPDs associated with a specific VA can be simulated in the sandbox with a special endpoint: https://app.moderntreasury.com/api/simulations/incoming_payment_details/create_async. See this article for additional details.

Using that special endpoint, the fields to use are:

  • type: the type of incoming payment, typically ach or wire.
  • direction: credit if funds are being sent to the VA or debit if funds are being drawn from the VA.
  • amount: the transaction value.
  • internal_account_id: the same id used in the VA section above.
  • virtual_account_id: the id of the VA to link to this IPD.

Once the IPD is generated in the sandbox, it will automatically associate with the VA and reconcile to a posted transaction, just as it would in production.

Ledger Transactions

The standard VA workflow often includes ledgering VA balances as IPDs are received. MT will automatically generate Ledger Transactions (LT) for IPDs if the VA and the VA’s underlying IA have been linked to their respective Ledger Accounts. This is called default ledgering.

Once the VA and IA have been linked to their respective Ledger Accounts, MT will automatically generate LTs for any IPDs created for the VA (including sandbox-simulated IPDs). Since the LT is linked to the IPD, its status updates as the status of the IPD changes.

Alternatively, if your organization needs to manually create LTs for IPDs to support more complex LTs than what is available through default ledgering, create LTs programmatically with the ledgerable_type set as incoming_payment_detail and ledgerable_id as the id of the IPD.

If using MT's Solution Architecture service, your assigned team member will provide guidance as needed for more complex workflows.

Originated Returns

There may be scenarios where your organization needs to reject an IPD, like when the receiving VA has been closed or has insufficient funds. You should determine the expected workflows where originated returns apply.

Depending on bank support, you may be able to originate ACH returns and/or wire returns via MT. See the following articles for additional details:

As described in the above articles, use the Create Return endpoint with the following required fields:

  • returnable_id: the id of the IPD
  • returnable_type: set to incoming_payment_detail
  • code: required for ACH returns. A full list of ACH return codes can be found on this page.
  • Use other fields as needed.

IPD Webhooks

The most noteworthy events/webhooks from this section are the IPD webhooks. IPDs alert you of incoming payments and allow you to trigger actions downstream as needed.

You can also listen to any of the three VA webhooks as needed. For LT webhooks, refer to the Ledgers section of this guide.

Testing Notes

As part of the testing process for this section, ensure that:

  1. All VA, NIA, IPD, and LT objects are being created as expected.
  2. Default ledgering is written to the correct LAs (if enabled).
  3. IPD Returns can be originated as expected.
  4. Critical identifiers, like the VA or NIA account_number, are being stored on the application side or presented to the end user.
  5. Required identifiers, like the ids of VAs, NIAs, IPDs, LTs, and Returns are being stored upon creation on the application side where needed for quick reference later.
  6. Required webhooks are being received and downstream actions are being executed as expected.

Moving to Production

After completing testing in the sandbox environment, you’ll be ready to transition to the live production environment. Similar to the sandbox, you should have a production-specific testing process to ensure a smooth and successful deployment. For Payments, this is often testing real-world money movement end-to-end for your specific use-case.

Remember, production (live-mode) differs from sandbox in real-world money movement timing, bank behavior, and data payloads for Transaction, Incoming Payment Detail (IPD), and Payment Reference objects.

Testing Methodology

Penny Testing

As part of your implementation with MT, your organization’s banks will be onboarded as Internal Accounts in MT. With your permission, the MT team will then help you conduct penny tests.

Penny tests are small transactions that verify the successful onboarding of a bank account. This will ensure your organization’s Internal Accounts are set up and configured as you expect.

API Testing

The majority of API testing will have been carried out during sandbox testing. However, there can be differences between behavior in sandbox and in production, so it’s good practice to test the expected API endpoints in the production environment to ensure there are no validation issues or unexpected behavior.

Since Payment Orders have real-world impact on money movement, use Approval Rules to gate your payments when testing this endpoint to prevent MT from sending the Payment Orders to the bank.

While some objects in MT can be deleted or archived as needed, make sure to clearly identify any objects created for production testing with descriptions and/or metadata. Use them exclusively for testing purposes.

Integration Testing

In this final step, run end-to-end testing for all workflows in production. Unlike the sandbox, these tests involve real money movement and real data from the bank. Similar to penny testing, the bank accounts involved in these tests should all be owned and controlled by your organization.

The goal of this step is to confirm everything - API calls, webhooks, reconciliation, ledgering, and your resulting application workflows - so your MT integration works as expected before officially launching in production.