Bank Transfer vs Transfer (Webhook)

Hello,

I am looking for assistance in reasoning about “bank transfers” in relation to “transfers”.

In the webhook event documentation it reads:

customer_bank_transfer_created: Occurs upon a POST request to the Initiate a transfer endpoint when sending funds from a Verified Customer’s bank, or when funds move from a receiving Verified Customer’s balance to their bank.

customer_transfer_created: Occurs upon a POST request to the Initiate a transfer endpoint when sending funds from a verified Customer’s balance, or to/from an unverified Customer’s bank.

The qualifiers lead me to believe that you will either get one or the other. A bank transfer is when we send funds “from a Verified Customer’s bank, or when funds move from a receiving Verified Customer’s balance to their bank”, while a transfer is when we send “funds from a verified Customer’s balance, or to/from an unverified Customer’s bank”. Is this a correct observation? Should I ever expect both of these webhook events? Are there implications related to each that I need to consider?

More broadly, why are there two different types of transfer webhooks? I think understanding this will be super helpful in building a successful integration.

Apologies if this is a duplicate question, I didn’t find anything providing me with answers. Thanks in advance.

Hi @bzswords, Thanks for posting! This is one of the more complex topics to explain, but something that is important to get right in your integration. Please feel free to reply back with any questions after reviewing my post! The main difference between when these two events are triggered ultimately comes down to:

  • The Customer record type(s) involved in the transaction; and
  • The Funding Source of the source and destination. (Bank or Balance)

Note: Only Verified Customer records, either individual or business, can hold a balance within the Dwolla network and therefore the customer_bank_transfer_* only apply to this Customer record type.

This seems to me to be the correct observation. To represent the possible events for a given call to the API to Transfer, here’s an example:

For a bank-to-bank transfer between two Verified Customers, funds will move like the following:

  1. Customer A Bank —> Customer A Balance (3-4 Biz days) (1-2 Biz days if Next-day ACH feature enabled)
  2. Customer A Balance —> Customer B Balance (instant)
  3. Customer B Balance —> Customer B Bank (1-2 Business days)

How that looks with webhooks:
customer_bank_transfer_created - Represents funds moving from source verified Customer’s bank to the Dwolla network.
customer_transfer_created - Represents funds transferring from Customer A to Customer B.
customer_bank_transfer_completed - Represents funds clearing either from a verified Customer’s bank to the Dwolla network or from the Dwolla network to a verified Customer’s bank
customer_transfer_completed - Represents funds completing to receiving Customer. Customer B’s balance
Step 3 (from above)
customer_bank_transfer_created - Represents funds moving from Customer B’s balance to their bank.
customer_bank_transfer_completed - Represents funds completing to Customer B’s bank.

You can expect both events if the Transfer is sourced from a Verified Customer’s bank and is destined to another Customer record. I would recommend setting up a webhook subscription in our Sandbox environment and testing out your payment flow, keeping the two bullet points above in mind when testing. You should be able to replicate the sequence of events triggered for your payment use case and track funds as they move from their source to the destination.

Again, please don’t hesitate to reach out if you have any follow up questions! We are working on some supplemental documentation to help better visualize Transfers and their related Events based on a given payment use case. :slight_smile:

This is very helpful, thanks Spencer.

For all of these webhook events, will they share the same resource ID to identify the transfer grouping all of this under the hood activity?

Secondly, what about a bank-to-bank scenario for a verified to unverified customer? Would it look like the following:

  1. Customer A Bank —> Customer A Balance (3-4 Biz days) (1-2 Biz days if Next-day ACH feature enabled)
  2. Customer A Balance —> Customer B Bank (1-2 Business days)

customer_bank_transfer_created - Represents funds moving from source verified Customer’s bank to the Dwolla network.
customer_bank_transfer_completed - Represents funds clearing either from a verified Customer’s bank to the Dwolla network or from the Dwolla network to a verified Customer’s bank
customer_transfer_created - Represents funds transferring from Customer A to Customer B’s bank.
customer_transfer_completed - Represents funds completing to receiving Customer. Customer B’s bank.

They will not share the same resource (Transfer) ID. It would look like what you outlined.
Each separate leg of the overall transaction will have its own unique transfer ID. To better represent this, I created this gist awhile back that may be a helpful reference. Linked to the specific payment use case you describe.

In terms of tying these unique transfer IDs together, there are a few helpful _links that are returned on the Transfer resource itself that you could use to traverse forward or backward in the overall transfer pipeline. Those links rels are called funding-transfer and funded-transfer. funded-transfer points to a transfer that is further ahead in the overall transaction pipeline. funding-transfer points to a unique transaction that is behind in the transaction pipeline.

For the example you mentioned, when the ACH debit completes to the source Customer records balance, it will result in an ACH credit being created to the receiving party. That will cause the funded-link rel to appear on the Transfer which points to the secondary transfer that is from the destination Customer balance en route to their bank. Here’s what that GET /transfers/{id} would look like:

{
"_links": {
    "self": {
        "href": "https://api-sandbox.dwolla.com/transfers/52fbb333-573a-e711-80f1-0aa34a9b2388",
        "type": "application/vnd.dwolla.v1.hal+json",
        "resource-type": "transfer"
    },
    "source": {
        "href": "https://api-sandbox.dwolla.com/funding-sources/c91d6516-1855-4d36-be7c-bc78cc7c52c3",
        "type": "application/vnd.dwolla.v1.hal+json",
        "resource-type": "funding-source"
    },
    "destination": {
        "href": "https://api-sandbox.dwolla.com/customers/b281413b-1d88-408b-a2b9-5fe5b6f16e63",
        "type": "application/vnd.dwolla.v1.hal+json",
        "resource-type": "customer"
    },
    "funded-transfer": {
        "href": "https://api-sandbox.dwolla.com/transfers/53fbb333-573a-e711-80f1-0aa34a9b2388",
        "type": "application/vnd.dwolla.v1.hal+json",
        "resource-type": "transfer"
    }
},
"id": "52fbb333-573a-e711-80f1-0aa34a9b2388",
"status": "processed",
"amount": {
    "value": "100.00",
    "currency": "USD"
},
"created": "2017-05-16T16:46:27.203Z",
"clearing": {
    "source": "standard"
}

}

This is great stuff. Thanks, Spencer.

1 Like

Just to be really clear:

After looking closely at the gist you linked to, it looks like in the Success outcome of Transfer Scenario 2 the customer_transfer webhooks all share the same Transfer ID of 53fbb333-573a-e711-80f1-0aa34a9b2388 while the customer_bank_transfer webhooks all share the same Transfer ID of 52fbb333-573a-e711-80f1-0aa34a9b2388.

So, circling back to terminology you presented in the last response, is it safe to make the claim that the funding-transfer is the customer_bank_transfer and the funded-transfer is the customer_transfer?

Yep, that’s correct for this specific use case! The ID 53fbb333-573a-e711-80f1-0aa34a9b2388 is what would be returned via the Location header when you call the API to create the transfer. I’d recommend storing this transfer ID and using it to reference later. This is the ID that would show up in the customer_transfer_* events. I refer to it as the “shared” ID because it’s the same for both Customer records involved in the transaction, and you’ll receive events for both Customers with this resource ID.

If you make a request to GET /transfers/53fbb333-573a-e711-80f1-0aa34a9b2388, you should see the funding-transfer link which corresponds to the resource ID contained in the customer_bank_transfer_* events.

Hey Spencer,

One scenario that will be common in the application we’re building is a Me-to-Me transfer, where funds will be coming out of one funding source associated with a customer and be sent to another funding source associated with the same customer. This customer will be verified.

Is there anything that changes for these kinds of scenarios as compared to what we have discussed above? Or is the Verified -> Verified scenario as described in the gist you posted accurate?

Hi @bzswords - for a Me-to-Me transfer, the gist that Spencer posted above is still accurate, except for the customer_transfer_created/completed webhooks, since there aren’t separate Customers involved in the transfer.

Additionally, you can refer to our guide on Me-to-Me transfers which also includes information on handling related webhooks!

Hope that helps! Let us know if you come across questions!

Thanks, Shreya. Apologies for all the questions but I’m finding the nuances of this confusing and all your answers have been helpful.

So in a Me-to-Me scenario, we will never get any customer_transfer_* webhooks…only customer_bank_transfer_* webhooks. What this implies is that, in the Dwolla system, there are only 2 transfers resources created, as compared to 3 (in a Verified -> Verified) scenario.

What I’m now trying to figure out is if I need to be storing in my own database references to all of these generated transfers, or if it is possible to get away with only storing the resource ID of the transfer created on the initial request. Do you all typically advise API integrations to keep a record of all seen transfer ID’s in the local database?

Apologies for the confusion! Hopefully I can help explain further about the me-to-me transfers -

Since this transfer occurs within the funding-sources of the same customer, the intermediary transfer (balance-to-balance transfer as seen in a Verified -> Verified scenario) does not need to occur. This causes a me-to-me bank-to-bank transfer to only have 2 transfers resources.

As for storing the different transfer IDs in your DB, typically we’d recommend storing all transaction ids that occur for a bank to bank transaction. That way you have better reconciliation in the event of an ACH return. If you store only the initial transfer ID (Transfer A), you can still retrieve the second leg of the transfer (Transfer B) via the API by following the "funded-transfer" link present in the response body of Transfer A.

Response body for example Transfer ID - 81643da1-b1b3-e911-811b-f08aa77f5aa3:

{
    "_links": {
        "self": {
            "href": "https://api-sandbox.dwolla.com/transfers/81643da1-b1b3-e911-811b-f08aa77f5aa3",
            "type": "application/vnd.dwolla.v1.hal+json",
            "resource-type": "transfer"
        },
        "source": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/707177c3-bf15-4e7e-b37c-55c3898d9bf4",
            "type": "application/vnd.dwolla.v1.hal+json",
            "resource-type": "funding-source"
        },
        "destination": {
            "href": "https://api-sandbox.dwolla.com/customers/cf3f1ad4-fc48-45d3-8aff-0ef5577b8a17",
            "type": "application/vnd.dwolla.v1.hal+json",
            "resource-type": "customer"
        },
        "funded-transfer": {
            "href": "https://api-sandbox.dwolla.com/transfers/a00ff82d-73b4-e911-811b-f08aa77f5aa3",
            "type": "application/vnd.dwolla.v1.hal+json",
            "resource-type": "transfer"
        }
    },
    "id": "81643da1-b1b3-e911-811b-f08aa77f5aa3",
    "created": "2019-08-01T15:32:05.620Z",
    "status": "processed",
    "amount": {
        "value": "225.00",
        "currency": "USD"
    },
    "individualAchId": "IQ8M922R"
}