Instant Payments - Dwolla Developer Portal

Overview

Instant Payments combine two powerful US-based payment networks to provide 24/7/365 processing of payments within minutes for banks and other financial institutions:

Both networks are exclusively for US domestic transfers, with RTP requiring participants to be US residents or persons domiciled in the United States. Payment speed and availability are the primary benefits of utilizing Instant Payments, as businesses can send and receive payments within seconds to eligible bank accounts 24/7/365. In addition, Instant Payments offer other benefits, including:

The core of the Dwolla Platform was built around a simplified connection to the U.S. banking infrastructure for businesses to easily initiate digital payments via the ACH Network. As the Dwolla Platform evolves, Instant Payments add a new processing channel for businesses, providing flexible payment capabilities to build within their own applications. While Instant Payments and ACH are similar in many ways, there are some key differences:

ACH Instant Payments (RTP/FedNow)
Sent via the ACH Network operators (either the Federal Reserve Bank or The Clearing House). RTP: Sent via the RTP® Network operator, The Clearing House.
FedNow: Sent via the FedNow Service, Federal Reserve.
Rules and regulations issued by National Automated Clearing House Association (Nacha). RTP: Rules and regulations issued by The Clearing House (TCH).
FedNow: Rules and regulations issued by the Federal Reserve.
Supports both credit (push) and debit (pull) transactions. Credit (push) transfers only - no debit (pull) capabilities.
Funds can take 1-3 business days to be available. Funds made available within seconds.
Agreed-upon processes for correcting erroneous transactions (i.e. reversal requests). Funds are irrevocable once sent.

Instant Payments is a premium feature available for Dwolla customers. Enabling Instant Payments does require additional Dwolla approvals before getting started. Please contact Sales or your Relationship Manager for more information on enabling this account feature.

Use cases and characteristics

Instant Payments support credit “push” transfers, whereas ACH supports credit push as well as debit pull transfers. Instant payments are particularly suited to support disbursement use cases. Whether your business is built around B2B, B2C, or a combination, you can power your application with Instant Payments.

Transaction limits

Instant Payments (defined as including both RTP and FedNow® Service) have specific transaction limits that are configured on a per-client basis. Understanding these limits is crucial for successful payment processing.

Daily transaction limits

Each client has a configurable daily transaction limit that applies to all instant payment transactions made under their account. This includes transactions initiated by the client and their customers.

Daily transaction limits are configured on a per-client basis and are not set by default. Contact your Relationship Manager to configure appropriate limits for your use case.

Per-transaction limits

Individual instant payment transactions are structured with a maximum limit of $500,000 per transaction. This limit applies regardless of your daily transaction limit configuration.

Error handling for exceeding limit

When a transaction exceeds the daily limit the Dwolla API will return a HTTP 400 ValidationError with specific details about the limit violation.

Initiate Transfer Request

Error Response

POST https://api.dwolla.com/transfers
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/vnd.dwolla.v1.hal+json

{
    "_links": {
        "source": {
            "href": "https://api.dwolla.com/funding-sources/0ce0900f-fe9e-49c9-ac3a-6e7daafdaaef"
        },
        "destination": {
            "href": "https://api.dwolla.com/funding-sources/469ccaed-76ec-4fd4-a3b4-4c1805fb225b"
        }
    },
    "amount": {
        "currency": "USD",
        "value": "150000.00"
    },
    "processingChannel": {
        "destination": "instant"
    },
    "instantDetails": {
        "destination": {
            "remittanceData": "ABC_123 Remittance"
        }
    }
}
{
  "code": "ValidationError",
  "message": "Validation error(s) present. See embedded errors list for more details.",
  "_embedded": {
    "errors": [
      {
        "code": "Restricted",
        "message": "Real Time Payment daily limit reached",
        "path": "/amount/value",
        "_links": {}
      }
    ]
  }
}

Once you reach your daily transaction limit, you cannot process additional instant payment transactions until the limit resets at midnight CT. Plan your payment volumes accordingly to avoid service interruptions.

Identifying an Instant Payment-enabled Funding Source

On the Dwolla Platform, Funding Sources allow bank accounts to be added or retrieved. Available for both a Dwolla Master Account and Customers (end users) resources, Funding Sources have represented payment accounts used for ACH and/or wire activities. Dwolla will be able to identify a bank account as Instant Payment-enabled upon creation of a Funding Source, so no additional information is needed from your end users or application.

Retrieving an Instant Payment-enabled Funding Source

When retrieving an existing Funding Source resource from the API, the response will contain a “channels” attribute which represents the different capabilities available for transfers. For a bank account, historically the only values available have been “ach” and “wire”. The example below represents how “real-time-payments” is returned within the “channels” array to identify an Instant Payment-eligible account (supporting either RTP, FedNow, or both).

"channels": [
  "ach",
  "real-time-payments"
]

The real-time-payments channel indicates eligibility for Instant Payments. The specific Instant Payments method used, RTP or FedNow, is determined internally based on availability and company preference when a transfer is initiated. This channel value remains the same regardless of whether the Funding Source supports RTP, FedNow, or both networks.

Initiating an Instant Payment transfer

In order to initiate a transfer with Instant Payment processing, an optional processingChannel JSON object must be included in the transfer request. The processingChannel object contains the destination key with a value of instant. You can also use real-time-payments as an acceptable alternative value. The processingChannel object will be returned when retrieving the transfer from the API, though the returned value may differ from the request value depending on the payment network used. An optional instantDetails object can be included in the transfer request body. This allows additional information to be passed to the payment recipient’s bank account about their Instant Payment credit transfer. For backward compatibility, you may also use rtpDetails, but instantDetails is recommended for new integrations.

You can also include an optional fees array on an Instant Payments transfer to collect a facilitator fee. The fee can be charged to either the sending or receiving party, and—just like on ACH—each fee is created as a separate transfer resource with a unique transfer ID, and does not affect the original payment amount. See Adding a facilitator fee below.

The following example assumes the sending party has funds pre-loaded to their balance Funding Source and that the destination party has a bank account connected that is Instant Payments-enabled.

HTTP

create_transfer.rb

create_transfer.php

create_transfer.py

createTransfer.js

POST https://api-sandbox.dwolla.com/transfers
Accept: application/vnd.dwolla.v1.hal+json
Content-Type: application/vnd.dwolla.v1.hal+json
Authorization: Bearer pBA9fVDBEyYZCEsLf/wKehyh1RTpzjUj5KzIRfDi0wKTii7DqY
Idempotency-Key: 19051a62-3403-11e6-ac61-9e71128cae77

{
    "_links": {
        "source": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/b268f6b9-db3b-4ecc-83a2-8823a53ec8b7"
        },
        "destination": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/ecf993e2-fa22-4cea-8022-c7861200288f"
        }
    },
    "amount": {
        "currency": "USD",
        "value": "10000.00"
    },
    "processingChannel": {
        "destination": "instant"
    },
    "instantDetails": {
      "destination": {
         "remittanceData": "ABC_123 Remittance Data"
      }
    }
}

...

HTTP/1.1 201 Created Location: https://api-sandbox.dwolla.com/transfers/636de847-7d02-e711-80ee-0aa34a9b2388


**Recommended approach for new integrations:** Use `instant` as the `processingChannel.destination` value and `instantDetails` for remittance data. This combination provides the most modern and future-proof approach for Instant Payments.

**Backward compatibility options:** You can also use `real-time-payments` as the processing channel and `rtpDetails` for remittance data, or mix and match as needed. Both `instantDetails` and `rtpDetails` are functionally equivalent and will work with both RTP and FedNow transfers.

### Adding a facilitator fee

Instant Payments transfers support the optional `fees` array, bringing facilitator fees to parity with ACH. To collect a fee, include a `fees` array alongside `processingChannel` in your transfer request. Each fee object contains a `_links.charge-to` link pointing to the [Customer](https://developers.dwolla.com/docs/api-reference/customers) or [Account](https://developers.dwolla.com/docs/api-reference/accounts) that will assume the fee—this may be either the sending or receiving party—and an `amount` object. Refer to the [Facilitator Fee](https://developers.dwolla.com/docs/facilitator-fee) resource article for the full behavior and reconciliation guidance. The following example builds on the request above, adding a `$2.00` fee charged to one of the parties involved in the transfer:

HTTP

{
    "_links": {
        "source": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/b268f6b9-db3b-4ecc-83a2-8823a53ec8b7"
        },
        "destination": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/ecf993e2-fa22-4cea-8022-c7861200288f"
        }
    },
    "amount": {
        "currency": "USD",
        "value": "10000.00"
    },
    "processingChannel": {
        "destination": "instant"
    },
    "fees": [
        {
            "_links": {
                "charge-to": {
                    "href": "https://api-sandbox.dwolla.com/customers/479ce4c8-385f-4cfa-9693-262c0c3b6408"
                }
            },
            "amount": {
                "value": "2.00",
                "currency": "USD"
            }
        }
    ]
}

Standard facilitator fee constraints still apply on Instant Payments: a fee must be at least $0.01, the sum of fees cannot exceed 50% of the original transfer amount, and each fee must be charged to a party involved in the transfer. See the Facilitator Fee article for full details.

Retrieving an Instant Payment transfer

When retrieving the transfer from the API, the response will contain either an rtpDetails object (for RTP transfers) or a fedNowDetails object (for FedNow transfers), depending on which payment network was used. Both objects have the same structure and contain a destination JSON object that includes:

These network-specific identifiers appear on the transfer API resource once the credit entry clears into the destination bank account.

The fedNowDetails object only appears in API responses and has the same structure as rtpDetails. You cannot include fedNowDetails in transfer creation requests - use rtpDetails or instantDetails for request payloads.

Request and response examples

RTP Transfer Response:

HTTP

retrieve_transfer.rb

retrieveTransfer.js

retrieve_transfer.py

retrieve_transfer.php

GET https://api-sandbox.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03
Accept: application/vnd.dwolla.v1.hal+json
Authorization: Bearer 0Sn0W6kzNicvoWhDbQcVSKLRUpGjIdlPSEYyrHqrDDoRnQwE7Q

{
  "_links": {
    "source": {
      "href": "https://api-sandbox.dwolla.com/accounts/0ee84069-47c5-455c-b425-633523291dc3",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "account"
    },
    "destination-funding-source": {
      "href": "https://api-sandbox.dwolla.com/funding-sources/a67d47f0-73de-4a6c-8de4-105d30aad395",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "funding-source"
    },
    "self": {
      "href": "https://api-sandbox.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "transfer"
    },
    "source-funding-source": {
      "href": "https://api-sandbox.dwolla.com/funding-sources/7dc2e1df-9a88-4d9a-868f-90b46f1defcc",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "funding-source"
    },
    "destination": {
      "href": "https://api-sandbox.dwolla.com/customers/3f65869e-61de-4efb-9b60-f6d0b9f804ed",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "customer"
    }
  },
  "id": "243fd252-3fcf-eb11-8134-d050ab358a03",
  "status": "processed",
  "amount": {
    "value": "1000.00",
    "currency": "USD"
  },
  "created": "2021-06-17T07:40:45.400Z",
  "processingChannel": {
    "destination": "real-time-payments"
  },
  "rtpDetails": {
    "destination": {
      "networkId": "20210617021214273T1BG27487110796028",
      "endToEndReferenceId": "E2E-RTP-20210617-001",
      "remittanceData": "ABC_123 Remittance Data"
    }
  }
}
transfer_url = 'https://api.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03'

# Using DwollaV2 - https://github.com/Dwolla/dwolla-v2-ruby (Recommended)
transfer = app_token.get transfer_url
transfer.status # => "processed"
var transferUrl =
  "https://api.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03";

dwolla.get(transferUrl).then(function (res) {
  res.body.status; // => 'processed'
});
transfer_url = 'https://api.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03'

# Using dwollav2 - https://github.com/Dwolla/dwolla-v2-python (Recommended)
fees = app_token.get(transfer_url)
fees.body['status'] # => 'processed'
<?php
$transferUrl = 'https://api.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03';

$transfersApi = new DwollaSwagger\TransfersApi($apiClient);

$transfer = $transfersApi->byId($transferUrl);
print($transfer->status); # => "processed"
?>

FedNow Transfer Response:

{
  "_links": {
    "source": {
      "href": "https://api-sandbox.dwolla.com/accounts/0ee84069-47c5-455c-b425-633523291dc3",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "account"
    },
    "destination-funding-source": {
      "href": "https://api-sandbox.dwolla.com/funding-sources/a67d47f0-73de-4a6c-8de4-105d30aad395",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "funding-source"
    },
    "self": {
      "href": "https://api-sandbox.dwolla.com/transfers/243fd252-3fcf-eb11-8134-d050ab358a03",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "transfer"
    },
    "source-funding-source": {
      "href": "https://api-sandbox.dwolla.com/funding-sources/7dc2e1df-9a88-4d9a-868f-90b46f1defcc",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "funding-source"
    },
    "destination": {
      "href": "https://api-sandbox.dwolla.com/customers/3f65869e-61de-4efb-9b60-f6d0b9f804ed",
      "type": "application/vnd.dwolla.v1.hal+json",
      "resource-type": "customer"
    }
  },
  "id": "243fd252-3fcf-eb11-8134-d050ab358a03",
  "status": "processed",
  "amount": {
    "value": "1000.00",
    "currency": "USD"
  },
  "created": "2021-06-17T07:40:45.400Z",
  "processingChannel": {
    "destination": "fed-now"
  },
  "fedNowDetails": {
    "destination": {
      "networkId": "20240115123456789FEDNOW123456",
      "endToEndReferenceId": "E2E-FEDNOW-20240115-001",
      "remittanceData": "ABC_123 Remittance Data"
    }
  }
}

The response will contain either rtpDetails (for RTP transfers) or fedNowDetails (for FedNow transfers) depending on which payment method was used. Both objects have identical structure but contain network-specific identifiers. This allows you to identify the specific payment network used for troubleshooting purposes. Processing Channel Behavior: The processingChannel.destination value in the response reflects the actual payment network used, regardless of the original request value:

This means that even if you specify real-time-payments in your request, if the destination bank only supports FedNow, the response will show fed-now to indicate the actual network used.

Webhook notifications

Webhook notification events will be processed in the same sequence as an ACH transfer. The primary difference is that once the transfer is created, the completion or failure events will be triggered moments later rather than days. The specific events include -

Event Topic Description
customer_bank_transfer_created Sent when the Instant Payment transfer is created for a Verified Customer
customer_bank_transfer_failed Sent if the Instant Payment transfer fails for a Verified Customer
customer_bank_transfer_completed Sent when the Instant Payment transfer is completed successfully for a Verified Customer
customer_transfer_created Sent when the Instant Payment transfer is created for an Unverified Customer or Receive-only User
customer_transfer_failed Sent if the Instant Payment transfer fails for an Unverified Customer or Receive-only User
customer_transfer_completed Sent when the Instant Payment transfer is completed successfully for an Unverified Customer or Receive-only User
customer_funding_source_rtp_enabled Sent when a funding source is identified as Instant Payment eligible
customer_funding_source_rtp_disabled Sent when an Instant Payment eligible funding source is later identified as ineligible

The webhook event names remain the same for both RTP and FedNow transfers. The customer_funding_source_rtp_enabled and customer_funding_source_rtp_disabled events are used for all Instant Payment eligibility changes, regardless of whether the funding source supports RTP, FedNow, or both networks. This means you’ll receive the same webhook events whether a funding source becomes eligible for RTP, FedNow, or both payment methods.

Error Codes

Error codes provide the reason a message did not complete and can be found on the payment Result.Code. The Result.Code will be OK if the payment was successfully sent/received.

Code Description
650 Cannot parse the message
690 Signature mismatch or verification error
AB05 Transaction stopped due to timeout at the Creditor Agent
AB06 Transaction stopped due to timeout at the Instructed Agent
AB08 Creditor Agent is not online
AB09 Transaction stopped due to error at the Creditor Agent
AC01 Account number is invalid or missing
AC02 Debtor account is invalid
AC03 Creditor account is invalid
AC04 Account closed
AC06 Account is blocked
AC07 Creditor account closed
AC10 Debtor account currency is invalid or missing
AC11 Creditor account currency is invalid or missing
AC13 Debtor account type missing or invalid
AC14 Creditor account type missing or invalid
ACWP Accepted without posting - receiving FI accepted the payment but has not yet posted to the account
AG01 Transaction is forbidden on this type of account
AG03 Transaction type is not supported/authorized on this account
AGNT Incorrect Agent
AM02 Specific transaction/message amount is greater than allowed maximum
AM04 Amount of funds available to cover specified message amount is insufficient
AM09 Amount received is not the amount agreed or expected
AM11 Transaction currency is invalid or missing
AM12 Amount is invalid or missing
AM13 Transaction amount exceeds limits set by clearing system
AM14 Transaction amount exceeds limits agreed between bank and client
BE04 Specification of creditor’s address, which is required for payment, is missing/not correct
BE06 End customer specified is not known at associated Sort/National Bank Code or no longer exists in the books
BE07 Specification of debtor’s address, which is required for payment, is missing/not correct
BE10 Debtor country code is missing or invalid
BE11 Creditor country code is missing or invalid
BE13 Country code of debtor’s residence is missing or invalid
BE14 Country code of creditor’s residence is missing or invalid
BE16 Debtor identification code missing or invalid
BE17 Creditor identification code missing or invalid
BLKD Payment has been blocked
COMM Error communicating with real time payments provider
DS04 Order was rejected by the bank side for reasons concerning content
DS0H Signer is not allowed to sign for this account
DS24 Waiting time expired due to incomplete order
DT04 Future date is not supported
DUPL Payment is a duplicate of another payment
FF02 Syntax error reason is provided as narrative information in the additional reason information
FF03 Invalid Payment Type Information
FF08 End to End ID is missing or invalid
FF10 File or transaction cannot be processed due to technical issues at the bank side
MD07 End customer is deceased
NARR Reason is provided as narrative information in the additional reason information
NOAT Receiving Customer Account does not support/accept this message type
OK Completed
RC01 Bank identifier code specified in the message has an incorrect format
RC02 Bank identified is invalid or missing
RC03 Debtor FI identifier is invalid or missing
RC04 Creditor FI identifier is invalid or missing
SL03 Token service not responding
TK01 Invalid Token
TK02 Sender Token Not Found
TK03 Receiver Token Not Found
TK04 Token Expired
TK05 Token Found with Counterparty Mismatch
TK06 Token Found with Value Limit Rule Violation
TK07 Single Use Token Already Used
TK08 Token Suspended
TM01 Invalid Cut Off Time
UE01 Technical error that may clear if the message is retried
1100 Any Other Reasons Reason is provided as narrative in the additional information
9909 Central Switch (RTP) system malfunction
9910 Instructed Agent signed-off
9912 Recipient connection is not available
9934 Instructing Agent signed-off
9946 Instructing Agent suspended
9947 Instructed Agent suspended
9948 Central Switch (RTP) service is suspended