Skip to main content

Act on SharedSavings Transactions

This sequence diagram is applicable if you have Savings Dreams enabled only (i.e. no Performance Dreams).

DES publishes "requested" transactions to act on through the /transactions endpoint, with a filter on ?state=requested. You can either subscribe to a webhook to get notified when there are new transactions to act on, or poll this endpoint regularly. Once a transaction is settled or failed, you tell DES by sending a PATCH request to the corresponding /transaction/{id} endpoint.

sequenceDiagram participant des as DES Backend participant bbe as Bank Backend opt Webhook registered des -->> bbe: POST /webhooks/transactions end bbe ->>+ des: GET /transactions?state=requested des -->>- bbe: List of transactions bbe ->> bbe: Settle or Fail each transaction async bbe ->> des: PATCH /transactions/{id} des -->> bbe: 200 OK

Here's an example of requested Deposit transaction in JSON format:

{
"type": "Deposit",
"id": <transactionId>,
"externalId": null,
"user": {
"type": "User",
"id": <userId>,
"externalId": <your user id>
}
"amountCents": 12300,
"toAccount": {
"type": "SharedSavings",
"id": <accountId>,
"externalId": <your account id>
}
"toDream": {
"type": "SavingsDream",
"id": <dreamId>
}
"state": "requested"
"requestedAt": 2023-03-27T16:41:00Z,
"settledAt": null,
"failedAt": null,
"errors": []
}

That's a lot of fields to digest. Thankfully, depending on your account setup most fields can normally be ignored.

One SharedSavings account per End User

With this account setup, you can store a mapping from user to account on your end during account provisioning. Given that, the only fields you have to consider in order to act on a transaction are:

{
"type": "Deposit",
"id": <transactionId>,
"user": {
"externalId": <your user id>
}
"amountCents": 12300,
}

This tells you that this particular user (with your externalId) has the intent to Deposit the amount amountCents from their current account to their DES SharedSavings account.

NOTE that this account setup allows DES to be completely unaware of any account ids, guaranteeing that it is impossible for DES to create fraudulent transactions, e.g. between End Users.

Withdrawals are exactly analogous to Deposits, with the only difference that the type is "Withdrawal".

Internal transactions between Dreams can be ignored entirely, as this is just internal bookkeeping in DES, without money changing account.

One SharedSavings account per Savings Dream

If you have a 1-to-1 mapping between accounts and Dreams, you also have to read the intended target account from the toAccount field. Given that you have set an externalId of your choosing on the account when creating it, this is the only Id that you have to read now to act on the transaction (you can ignore the DES-internal id).

{
"type": "Deposit",
"id": <transactionId>,
"user": {
"externalId": <your user id>
},
"toAccount": {
"externalId": <your account id>
},
"amountCents": 12300
}

Withdrawals are exactly analogous to Deposits, with the only difference that the type is "Withdrawal" and toAccount is replaced with fromAccount.

Internal transactions between Dreams can not be ignored with this account setup, as this means that money should move between different accounts.´ Internal transaction has both a toAccount and a fromAccount.

Settling a Transaction

In order to settle a transaction, the only field that needs updating is the settledAt timestamp:

PATCH /transactions/{id}
{
"transaction": {
"settledAt": <DateTime>
}
}

Failing a Transaction

In order to fail a transaction, you just have to set the failedAt timestamp..

PATCH /transactions/{id}
{
"transaction": {
"failedAt": <DateTime>,
}
}