Customer funding source removed - unique ids reused?

We are running into a somewhat obscure issue with Customer funding sources. On 11/1, a user of ours visited their “wallet” page (the location on our site to update their Dwolla info) and seemed to have gone through at least 3 iterations of deleting and adding new bank information. The timeline of user action to dwolla webhook notification shows as follows (approx. UTC time):

15:59 – User deletes funding source

15:59 – Webhook customer_funding_source_removed (webhook: b912627b-4e83-4535-9fc3-1b4b9037850c, resource: 4bd4d6f4-751b-4862-8923-da410d913dbe)

16:00 – User deletes funding source

16:00 – Webhook customer_funding_source_removed (webhook: 06089589-08e5-4105-81da-d77771dcbc4d, resource: 094075c6-96c0-4b24-bf25-56792c30cb5f)

16:03 – User creates funding source

16:03 – Webhook customer_funding_source_added (webhook: 360b275b-2f11-4967-b944-f94a8383f29f, resource: acd17513-36af-4b1c-ae29-0aba89029fa4)

16:03 – User deletes funding source

16:05 – User creates funding source

…almost an hour later…

17:04 – Webhook customer_funding_source_removed (webhook: 2c2cba5c-1592-4746-bdeb-18b8271f9001, resource: acd17513-36af-4b1c-ae29-0aba89029fa4)

17:05 – Webhook customer_funding_source_added (webhook: 401d72e6-177c-4dfa-b0df-4b314e759138, resource: acd17513-36af-4b1c-ae29-0aba89029fa4)

On receipt of the customer_funding_source_removed webhook, we would remove any existing funding source in our system to handle the case outlined in the events API documentation (…when Dwolla systematically removes a funding source upon receiving certain ACH return codes when a transfer fails). The ordering of the webhook typically falls in sequence but also wouldn’t be a problem, except that it appears that the unique id of the funding source is being reused. Is that possible? It’s likely our user entered the same data more than once on successive updates to their payment info. So, if it’s a related hashing of the user-entered data, that could explain the uniqueness issue.

Should funding source ids be considered fully unique over a certain amount of time? If not, how do you suggest I handle the case for removing resources as cleanup for items automatically removed by Dwolla?

It looks like the webhook for this event was retried multiple times. The original attempt returned a status=503 from your server which is why it was put on our retry queue.

Yes, definitely possible. If a previously removed bank with an unverified status is added back within 48 hours of initial creation then Dwolla will return the existing Funding Source ID (essentially reactivating). It looks like the user added, removed, then added again. Here are the timestamps of those requests:

  • 2022-11-01 16:03:03,679 | method=POST | statusCode=201 | url=
  • 2022-11-01 16:03:55,644 | method=POST | statusCode=200 | url=
  • 2022-11-01 16:05:29,206 | method=POST | statusCode=201 | url=

The only case where the Funding Source ID wouldn’t be unique on creation would be for the use case I described above. A user adds a bank and it has an unverified status. They then remove and readd within 48 hours of the initial created timestamp of that funding source.

Ok thanks for the info here. I should be able to confirm the resource in question from the customer_funding_source_removed webhook is in fact removed with an API call before removing it on our side. One final question, are retried webhook ids also unique?

Yes, if you are parsing the list webhooks for a subscription endpoint then you’ll see that each webhook will contain it’s own unique ID. There will also be an attempts array that contains a list of webhook attempts with each containing their own unique ID (see example below). Keep in mind: You cannot locate these webhook IDs within the actual payload itself as a webhook delivers an Event object. Therefore, it’s recommended to setup your webhook handler for idempotent Event processing to prevent processing the same event more than once.

"_links": { 
"id": "ac608c16-9b3a-4f79-8069-dcbc1835b528",
"topic": "customer_bank_transfer_created",
"accountId": "ad5f2162-404a-4c4c-994e-6ab6c3a13254",
"eventId": "b9097d7d-3455-465c-aedd-8477c208dea1",
"subscriptionId": "18e88c7f-46b3-4b99-aab9-47577044bc40",
"attempts": [ 
            "id": "0f777546-c74d-4400-99ae-b2581c847658",
            "request": {
                "timestamp": "2022-10-27T20:04:32.780Z",
                "url": "",
                "headers": [
                "body": "{\"id\":\"b9097d7d-3455-465c-aedd-8477c208dea1\",\"resourceId\":\"134bbf90-3256-ed11-8149-a62fd429f038\",\"topic\":\"customer_bank_transfer_created\",\"timestamp\":\"2022-10-27T20:04:32.456Z\",\"_links\":{\"self\":{\"href\":\"\"},\"account\":{\"href\":\"\"},\"resource\":{\"href\":\"\"},\"customer\":{\"href\":\"\"}},\"created\":\"2022-10-27T20:04:32.456Z\"}"
            "response": {
                "timestamp": "2022-10-27T20:04:33.287Z",
                "headers": [],
                "statusCode": 404,
                "body": ""
1 Like