Almost every modernization plan we write has the same step three: introduce a proper API layer. Not because APIs are fashionable, but because nothing else you want to do is possible without one.
A mobile app needs it. A customer portal needs it. A partner integration needs it. Any AI feature that has to read your data needs it. Until that layer exists, each of those is a separate project that reaches into the database on its own terms, and you end up with four implementations of the same business rule that disagree by the end of the year.
Where teams start, and why it goes wrong
The usual first instinct is to expose the tables. Generate endpoints from the schema, return the entities, let the client work it out.
It is quick and it feels like progress, but you have not built an API — you have built a second, less safe way to run SQL. Three problems follow:
Your schema becomes public. Every consumer now depends on column names and table structure. You cannot refactor the database without breaking a mobile app you shipped last year.
The business rules are left behind. The reason an order cannot move to "dispatched" without a signed delivery note lives in the application. Expose the table and that rule is now optional.
The chattiness is the client's problem. Rendering one screen takes eleven requests, which is fine on a desk and miserable on a phone with poor signal.
Model the operations, not the tables
A useful API describes what the business does, not what it stores.
The difference shows up immediately in the shape of the endpoints. Instead of PATCH /orders/123 { "statusId": 4 }, you want POST /orders/123/dispatch, carrying the delivery note reference. The second one can enforce the rule, write the audit entry, fire the notification and reject the call when the preconditions are not met. The first one cannot, because it does not know why the value is changing.
Design the endpoints from the screens and workflows that will consume them. If the mobile app's job list needs project name, next task, and overdue count, that is one endpoint returning exactly that — not three generic ones the client has to stitch together.
The seam matters more than the framework
The hard part is rarely ASP.NET Core. It is finding a place to stand.
In a well-layered application, the service layer already exists and the API is a thin controller over it. In an older one, the logic is inside code-behind, or a .aspx page, or the stored procedure we wrote about previously. There is no seam, so you have to make one.
The approach that works: extract the logic for one workflow into a service class that both the existing screen and the new endpoint call. One workflow, not all of them. The existing page keeps working — it is now calling the extracted service instead of doing the work inline — and the API gets its first real endpoint. Repeat per workflow, as the need arises.
This is slower than a big-bang rebuild and it is the reason the application never stops working.
Decisions worth making once, early
Versioning. Put a version in the URL from day one, even with a single consumer. Retrofitting versioning after a mobile app is in the App Store is genuinely painful, because you cannot make people upgrade.
Authentication. Decide early whether the API serves your own clients, third parties, or both. They have different needs, and bolting the second onto a design that assumed the first is a rewrite.
Errors. Pick one error shape and use it everywhere. A consumer that has to handle four different failure formats will handle none of them properly.
Documentation. Swagger/OpenAPI from the first endpoint. Not for the public — for the developer six months from now, which may well be you.
What it unlocks
Once the layer exists, the things that previously looked like separate projects become extensions of what you already own. The mobile app is a client. The customer portal is a client. The partner integration is a client with narrower permissions. An internal AI assistant reading project data is, again, a client — and it inherits the same permission model rather than being given a database login and a prayer.
That is why this step sits where it does in the plan. It is not the most visible work you will do, and it is the one that determines what is possible afterwards.