All news
ArchitecturePayticalEngineering

Generating the API client instead of hand-writing it

22 May 2026 · 3 min read

Paytical generates its type-safe frontend API client directly from the backend's contract, so the two can never quietly drift apart.

A frontend that calls a backend API has to agree with that backend on what the data looks like: field names, types, which fields are optional, what a given endpoint actually returns. The usual way that agreement gets maintained is by hand: someone writes TypeScript interfaces that mirror the backend's DTOs, and hopes to remember to update them every time the backend contract changes. That hope is where the drift creeps in. A backend field gets renamed, a response shape changes shape slightly, and the hand-written frontend types quietly stop matching reality until something breaks at runtime, well past the point where a compiler could have caught it.

Paytical avoids that category of bug by not hand-writing the client at all.

The backend's contract is the source of truth

Paytical's .NET backend already describes its own API surface as a machine-readable contract. Rather than treating that as documentation for a human to read and manually translate into frontend types, the frontend's API client is generated directly from it. When the backend's contract changes, regenerating the client produces frontend types that match, automatically, without a person needing to remember to update anything by hand.

This turns a class of bugs that used to only surface at runtime, calling code and backend disagreeing about a field's name or shape, into a compile-time type error instead. If the frontend code references a field the backend no longer returns, or gets a type wrong, the build fails immediately rather than the mismatch surfacing later as a confusing runtime error in production.

Why this matters more for Paytical specifically

Paytical exists to visualize complex payment flows: interactive diagrams built on React Flow, backed by data-grid analysis in AG Grid, both driven by whatever the API actually returns. A tool whose entire value is making complex financial data trustworthy to look at can't afford a silent mismatch between what the backend sends and what the frontend assumes it's receiving. Wrong data rendered confidently is worse than no data at all in a tool people use to understand how money moves through a system.

Caching sits on top, not bolted onto each call

The generated client handles the shape of each request and response; TanStack Query sits on top of it managing when data actually gets fetched, cached, and invalidated. Real-time query management matters here because payment-flow data isn't static: positions change, new transactions land, and a flow diagram showing stale data is actively misleading rather than just slightly out of date. Centralizing that caching and invalidation logic in one place, rather than scattering ad hoc fetch-and-cache logic across every component that needs data, is what keeps the app's behavior predictable as the number of views and data sources grows.

Generating the client and centralizing the caching layer both come from the same underlying principle: don't let something that can be derived automatically and consistently be reimplemented by hand in multiple places, since every hand-written copy is another place for the two sides to eventually disagree.

See how this plays out across the product on Paytical's page.

Have a system in mind?

We design and build custom systems end to end. Tell us about your idea and let's make it real.