Chapter 1 — The Problem That Started It All
Every major fintech product begins with something that feels almost too simple.
In our story, the request was:
“Let our users move money from their bank account into an investment account without feeling any pain.”
No awkward forms.
No multi-day confusion about “pending transfers.”
No uncertainty about whether money has landed or whether investing is available.
Just a feeling of flow.
But behind that seemingly easy request lived two enormous ecosystems — the U.S. banking system, with its ACH rules, identity requirements, return codes and cutoff windows… and the brokerage world, with its compliance standards, account approvals, journals, settlements, and trading gates.
To build what the client imagined, we needed two powerful partners:
Dwolla, for bank account verification and ACH/RTP transfers.
Apex, for creating brokerage accounts and enabling real investing.
And between them, INSART had to build a bridge sturdy enough to handle compliance, information flow, errors, asynchronous events, and real users.
This case study is the story of that bridge.
Chapter 2 — The INSART Way of Beginning
The first thing INSART always does is slow down.
Before touching the keyboard, we gather product managers, compliance officers, engineers, and architects and ask a simple question:
“What does the user think is happening?”
Because the user doesn’t care that Dwolla calls them a “customer,” that Apex calls them an “account holder,” or that ACH transfers have return codes like R01, R02 or R29.
The user only cares whether money is moving.
We mapped the experience from their perspective:
A user:
signs up
verifies identity
connects a bank account
deposits money
is approved for investing
sees money in their brokerage account
starts buying and selling
But inside the platform, that single beautiful path involves dozens of state changes, validations, event notifications, retries, reconciliations and compliance decisions.
That’s where INSART’s architecture begins — by understanding that two worlds need to feel like one.
Chapter 3 — Designing the Financial Highway
We designed the system the same way one would design a highway: with lanes, guardrails, and clear direction.
The high-level architecture looked like this:
Frontend (Web/Mobile)
|
API Gateway
|
┌──────────────────────────────┐
| Services |
| |
| • Identity & Compliance |
| • Dwolla Funding Engine |
| • Wallet & Ledger |
| • Apex Brokerage Engine |
| • Event Gateway |
| • Orchestration Layer |
└──────────────────────────────┘
|
Dwolla API ←→ Apex APIThere is no “shared data model” between Dwolla and Apex, so INSART built an internal language — a normalized model describing:
a user
a funding source
a transfer
a brokerage account
a journal
a settlement
a notification
It allowed us to translate Dwolla’s world into Apex’s world and vice versa.
Chapter 4 — Dwolla: Building Trust With the Banking System
The first half of the journey lives in Dwolla’s ecosystem.
The moment a user signs up, INSART’s Identity Service creates a Dwolla Customer behind the scenes:
// dwollaCustomer.ts
export async function createDwollaCustomer(user: User) {
return await dwollaClient.post('/customers', {
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
type: 'personal',
address1: user.address1,
city: user.city,
state: user.state,
postalCode:user.postalCode,
dateOfBirth: user.dob,
ssn: user.ssn4
});
}Dwolla responds with a URL like https://api.dwolla.com/customers/<uuid>.
We store that in the internal user profile and immediately monitor its status:
“verified”
“document”
“retry”
“suspended”
If Dwolla needs more documents, we request them.
If Dwolla flags something, we freeze funding.
Everything happens automatically.
Bank linking begins once identity is verified.
The user verifies their bank through Plaid or a similar provider.
We exchange the Plaid token for a Dwolla funding source:
// addFundingSource.ts
export async function attachBankAccount(dwollaCustomerUrl: string, processorToken: string) {
return await dwollaClient.post(`${dwollaCustomerUrl}/funding-sources`, {
plaidToken: processorToken
});
}Within seconds, the bank is connected.
Chapter 5 — Dwolla Transfers: Money On the Move
When a user chooses to deposit, say, $300, we create a Dwolla transfer:
// transferFunds.ts
export async function initiateDwollaTransfer(sourceUrl: string, destinationUrl: string, amount: string) {
return await dwollaClient.post('/transfers', {
_links: {
source: { href: sourceUrl },
destination: { href: destinationUrl }
},
amount: {
currency: 'USD',
value: amount
}
});
}From here, Dwolla enters its own ecosystem:
ACH processing
settlement timing
potential return codes
cutoff windows
risk monitoring
INSART built a Funding Engine that listens to every Transfer Event Dwolla emits:
// dwollaWebhook.ts
router.post('/dwolla/webhook', async (req, res) => {
const event = req.body;
await fundingService.handleDwollaEvent(event);
res.status(200).send('OK');
});Inside handleDwollaEvent we interpret events like:
transfer_created
transfer_completed
transfer_failed
customer_suspended
We update our internal ledger, notify the user, and decide whether the money is now ready to be pushed toward Apex.
Chapter 6 — Apex: Turning Dollar Amounts Into Investing Power
Once money arrives on the platform, the second world begins — Apex.
Apex requires detailed investor profiles, so we built a structured onboarding flow:
// createApexAccount.ts
export async function createApexAccount(user: User) {
const payload = {
accountType: 'INDIVIDUAL',
personalInfo: {
name: user.fullName,
address: user.fullAddress,
ssn: user.ssn,
dob: user.dob
},
disclosures: {
employmentStatus: user.employment,
industryAffiliation: user.industryAffiliation,
investmentExperience: user.experience
}
};
return await apexClient.post('/accounts', payload);
}Once Apex approves the account, they issue an accountNumber.
From this point onward, the user has:
a verified Dwolla customer
a verified funding source
a funded wallet
a brokerage account on Apex
money waiting to enter that account
Which brings us to the most delicate part.
Chapter 7 — Bridging Dwolla Money Into Apex Accounts
Dwolla settles money into the platform wallet.
But money must reach the Apex account before the user can trade.
INSART built a Journal Transfer Service:
// journalTransfer.ts
export async function sendFundsToApex(brokerageAccount: string, amount: number) {
return await apexClient.post('/journals', {
accountNumber: brokerageAccount,
amount: amount.toFixed(2),
currency: 'USD'
});
}Before initiating a journal, our Orchestration Layer checks:
has the user passed all compliance checks?
has the Dwolla transfer fully settled?
has the ledger confirmed available balance?
is the Apex account active?
are there any freezes or restrictions?
Only when everything is green do we push the funds to Apex.
Once the journal is posted, Apex sends a webhook:
// apexWebhook.ts
router.post('/apex/webhook', async (req, res) => {
await brokerageService.processApexEvent(req.body);
res.status(200).send('OK');
});When we receive JOURNAL_POSTED, we notify the user:
“Your funds are now available for investing.”
Because that is the moment everything becomes real.
Chapter 8 — Event-Driven Reality
In financial systems, everything meaningful happens asynchronously.
Dwolla and Apex both send event streams — dozens of messages for every user action.
INSART built a unified Event Gateway to handle both worlds:
// eventGateway.ts
export async function processEvent(event: any) {
if (event.source === 'dwolla') {
return fundingService.handleDwollaEvent(event);
}
if (event.source === 'apex') {
return brokerageService.handleApexEvent(event);
}
}This is how we maintain a single truth, even though the outside world is noisy and asynchronous.
The Event Gateway keeps:
ledger balances updated
account statuses accurate
notifications real-time
compliance logs complete
reconciliation predictable
It is the heartbeat of the system.
Chapter 9 — Launch: When The System Met Real Users
When the first batch of users entered the platform, they experienced what we hoped they would:
They connected their bank.
Added money.
Opened an investment account.
Saw money arrive.
Started trading.
Not a single one realized how many conditions had been checked behind the scenes.
They never saw a Dwolla return code.
They never encountered an Apex rejection payload.
They never saw the internal ledger.
They never realized that half the operations were asynchronous.
All they felt was flow.
That’s the magic of a system designed to hide the machinery and show only the outcome.
Chapter 10 — What This Integration Meant for INSART
This project wasn’t “two integrations.”
It was building a financial highway.
Dwolla controlled where money starts.
Apex controlled where money becomes investable.
INSART controlled everything that makes the experience coherent.
We learned that building for the user means:
translating complexity into clarity
turning delays into notifications
turning events into state
turning compliance into design
turning multiple systems into one story
And this is exactly what INSART specializes in.
Conclusion — The Highway Is Built, and It Works
Today, the rails we built handle:
identity verification
bank linking
ACH transfers
wallet management
brokerage account creation
funds journaling
real-time event syncing
portfolio readiness
and eventually trading
The beauty of it?
Users don’t think about any of this.
They just trust that when they click “Deposit,” the money shows up.
And when they click “Invest,” the trade flows.
That trust — invisible, silent, earned — is the highest compliment any fintech builder can receive.
INSART built the rails that made that trust possible.










