← Back to blog

API Design for an MVP: What to Decide Before You Build

October 21, 2026
API Design for an MVP: What to Decide Before You Build

Design the API for your MVP as a small, written contract that covers one core workflow, build it in plain REST with boring conventions, and leave everything else out. The contract matters more than the code behind it, because your web app, your mobile app, your payment provider and the next developer will all depend on it. Get the contract roughly right in a few days and you save weeks later.

I'm Hanad Kubat, a senior software engineer in Vienna. I build first real versions of products for founders at a fixed price. This guide is what I walk through with clients before the first line of code.

Hanad Kubat
hanadkubat.com
Build Your First Version Properly
Hanad builds working software for founders at a fixed price, with the scope and timeline agreed before development begins.
Explore first-version builds

Key takeaways

  • Write the contract first: a list of resources, endpoints, inputs, outputs and errors for one core workflow. Everything else waits.
  • Default to REST with JSON. Choose GraphQL, WebSockets or webhooks only when a specific feature demands them.
  • Decide authentication, ownership and error format on day one. These are the parts that hurt most to change after launch.
  • Design for failure from the start: idempotent writes, predictable errors, pagination and versioning you can live with.
  • An MVP API is not a throwaway. If real users depend on it, the next developer has to be able to read it.

Table of Contents

What an MVP API actually is

An API defines how pieces of software talk to each other, in the same way a user interface defines how a person uses an app. VMware's white paper on API products makes this comparison, and it is a useful way to think about it. Your screens are one consumer of the API. Your phone app, a Stripe webhook, a partner's script and an AI agent may become others.

For an MVP, that has a practical consequence. You are not designing a public developer platform. You are designing the internal seam between your front end and your data, plus the few places where outside systems touch you. Keep it that small, but write it down as if someone else will read it, because someone will.

I see two failure modes in founder projects:

  1. No design at all. The front end was generated or hacked together, and the "API" is whatever the database client happens to expose. It works in the demo. It breaks when you add a second user role, or when a security reviewer asks who can read what.
  2. Too much design. Forty endpoints, versioned namespaces and a GraphQL layer for an app that has one workflow. This burns the budget before anyone has used the product.

The target is between the two: a contract for one core workflow, built properly.

Start from the workflow, not the database

Before naming a single endpoint, write the core workflow as plain sentences. For a booking tool for a physiotherapy practice, it might be:

  • A patient picks a time slot and books it.
  • The practice sees the booking and confirms or declines it.
  • The patient gets an email and can cancel up to 24 hours before.

Every verb in those sentences is a candidate for an endpoint. Every noun is a candidate resource: slot, booking, patient. Anything that does not appear in a sentence like this is not part of the MVP API.

This is the same discipline I describe in how I think about MVP architecture: the structure should serve the one thing your first users must be able to do. If you are still deciding which features make the cut, this piece on MVP features that matter helps you trim first.

Turn sentences into a resource table

A one-page table is enough for most MVPs. For the booking example:

ActionMethod and pathWho can call it
List open slotsGET /slots?from=&to=Anyone signed in
Book a slotPOST /bookingsPatient
View my bookingsGET /bookingsPatient (own), staff (all)
Confirm or declinePATCH /bookings/{id}Staff
CancelDELETE /bookings/{id}Patient (own), staff

The third column is the one founders skip. Writing who can call each endpoint forces the access-control conversation early, when it costs a sentence instead of a rewrite.

Design the contract first

The Software Engineering Guide's chapter on APIs puts it plainly: the interface is a deliberate product decision, not a byproduct of implementation. It also lists two principles I treat as non-negotiable even on a four-week build: optimize for the consumer's experience, and treat backward compatibility as a promise.

Google Cloud's guide to API development describes the same design-first approach, using a specification language such as the OpenAPI Specification to sketch endpoints, data models and authentication before code exists. The OpenAPI Specification is a machine-readable format that tools can use to generate documentation, code and tests.

For an MVP I use it like this:

  1. Write the contract for the core workflow in OpenAPI, one file.
  2. Share it with whoever builds the screens, or with the founder if they are reviewing.
  3. Generate documentation and typed client code from it, so the front end and back end cannot drift apart.
  4. Treat changes to the file as product decisions, reviewed like any other.

This takes a few days at most for a focused scope. It is also the cheapest moment to find out you misunderstood your own product.

REST, GraphQL, webhooks: choose by need

The freeCodeCamp overview of API integration patterns draws a useful line: for simple request-response integration, REST, RPC or GraphQL can all work, while real-time needs point to polling, WebSockets or webhooks. That matches what I see in practice.

NeedPatternWhy
Screens that read and write your dataREST with JSONEveryone knows it, every tool supports it, easy to debug
Many different clients that each need different slices of dataGraphQLWorth it only once you really have that problem
Another service tells you something happened (a payment, a signature)WebhookThey call you, you do not poll
Live updates, chat, collaborative editingWebSockets or server-sent eventsOnly for features that truly need real-time

My default for an MVP is REST. It is deliberately boring, and boring is a feature: the next developer you hire already knows it. GraphQL is a fine technology, but it adds a schema layer, caching questions and tooling decisions that a one-workflow product rarely earns back.

A small caution on real-time: founders often ask for it because a competitor has it. Ask whether a page refresh every 30 seconds would actually hurt your first ten users. Usually it would not.

The decisions that are expensive to change later

Most API choices are cheap to revisit. A handful are not. Spend your design time here.

Authentication and ownership

Decide how users sign in and what each role may do before anything else. The rule I build around: every request carries an identity, and every query that touches user data filters by that identity on the server. Never rely on the front end to hide data.

If you expect enterprise customers, they will eventually ask for single sign-on. You do not need to build it now, but you should not design yourself out of it. This walkthrough of SAML SSO for SaaS is a good picture of what that request looks like when it arrives, and it is easier to meet if your user and organization model is clean from the start. If security is a bigger concern for your product, I wrote about engineer-led MFA for SaaS separately.

Identifiers and data shape

Use opaque IDs (UUIDs or similar) in URLs, not sequential integers that leak how many customers you have. Pick one date format (ISO 8601, in UTC) and one naming convention for fields and stick to it everywhere. Inconsistency here is the first thing that makes an API feel amateur.

Error format

Pick one error shape and use it for every failure. For example:

{
  "error": {
    "code": "slot_unavailable",
    "message": "This slot was just booked.",
    "field": null
  }
}

Use correct HTTP status codes (400 for bad input, 401 for not signed in, 403 for not allowed, 404 for not found, 409 for conflicts, 429 for rate limits). A stable machine-readable code lets the front end show a helpful message without parsing text. The Software Engineering Guide calls this making the easy thing correct: sensible defaults and predictable errors.

Money and external systems

Anything involving payments deserves extra care. Never calculate prices on the client. Let the server decide what to charge, create the payment with your provider, and treat the provider's webhook as the source of truth for whether someone paid. Your API should record that fact, not assume it.

Server, payment provider, webhook, and API flow

Design for failure, even in an MVP

Networks drop. Users double-click. Webhooks arrive twice. The Software Engineering Guide lists idempotency (a repeated request has the same effect as a single one), retries and related safeguards under designing for failure, and this is where prototypes built with AI tools most often fall over.

The concrete version for a write endpoint: the client sends a unique key with the request. If the same key arrives again, the server returns the first result instead of creating a second booking or a second charge. Stripe documents this pattern well in its idempotent requests reference: you provide an idempotency key, and a retry after a connection error does not repeat the operation. You can copy that pattern for your own POST endpoints that create things with side effects.

A short checklist for every endpoint that changes data:

  • Does it validate input on the server, not just in the form?
  • What happens if it is called twice in a row?
  • What happens if it fails halfway, after charging a card but before saving the order?
  • Does it return an error the front end can act on?
  • Is the action logged somewhere you can look at when a customer complains?

If you cannot answer these for the endpoints in your core workflow, you do not have a working version yet, you have a demo.

Pagination, filtering and versioning without overdoing it

Three small things save pain later.

Pagination. Any endpoint that returns a list should be paginated from the start, even if you have twelve records. Adding it later breaks every consumer. Cursor-based pagination ("give me the next 20 after this ID") is more robust than page numbers when data changes.

Filtering. Support only the filters your screens use. Query parameters like ?status=confirmed&from=2026-11-01 are enough.

Versioning. The Software Engineering Guide's rule is that breaking changes need a new version and a migration path. For an MVP, I put the version in the path (/v1/...) and then change nothing about it unless something breaks. Adding fields is safe. Removing or renaming them is the breaking change. If your only consumer is your own front end, you can deploy both together, but the /v1 prefix costs nothing and keeps your options open.

Where to put third-party integrations

Most MVPs touch outside services: payments, email, a CRM, maybe an LLM. The question is where that logic lives.

For one or two integrations, keep them in your own backend, behind your own endpoints and webhook handlers. Your front end should never talk to a payment provider's secret-key API or an LLM directly. The server holds the keys, validates the request and decides what happens.

As integrations multiply, some teams move that logic into a managed platform, a pattern described in this piece on integration architecture: your product fires events, and the platform handles routing and transformation. That can make sense later. At MVP stage it is usually one more thing to pay for and learn. If you are weighing how connected tools and automated publishing fit into a product, this article on API-led integration layers shows how a layered approach looks in a content workflow, which is a useful contrast to a simple first build.

Two rules I keep either way:

  • Wrap each external service behind a small function of your own, so swapping it later touches one file.
  • Verify the signature of every incoming webhook, and make the handler idempotent, because providers retry.

A realistic scope for a first version

To make this concrete, here is roughly what "API design for an MVP" means in a four-week build:

  1. Days 1 to 3: workflow written out, resource table, OpenAPI file for the core workflow, auth and roles decided.
  2. Week 1 to 2: data model, endpoints, validation, error format, authentication.
  3. Week 2 to 3: front end connected to the contract, payment or email integration, idempotency on the writes that matter.
  4. Week 3 to 4: tests on the core workflow, deployment, logging, documentation, handover.

The stack I use for this is TypeScript, Next.js, Node, SQL and Cloudflare Workers, plus Stripe when payments are involved. None of it is exotic. The point is that any competent developer can pick it up later. For a view of how the surrounding engineering decisions fit together, see how engineering drives MVP success, and for the UI side of the same contract, the role of UX in an MVP.

My perspective: the API is the part you will live with

When a founder brings me a prototype built in Lovable, Bolt, Bubble or similar, the screens are rarely the problem. The problem is that nobody decided what the system's rules are. Who owns a record? What happens when a payment fails? What does the front end do when the server says no? The prototype answered those questions by accident, in different ways on different pages.

So I treat the API as the written version of your business rules. I would rather spend the first days of a build agreeing on that contract with you than rush into screens, because it is what lets you swap a designer, add a mobile app or hand the code to another developer without starting over. You own the code from the first commit, and a clear contract is what makes owning it worth something.

I also tell founders when they do not need custom work. If a spreadsheet and an off-the-shelf form tool do the job for your first ten customers, use them and save the money. Custom API design pays off when the workflow is the product, or when something is already breaking under real users.

— Hanad Kubat

Want the first version built properly?

I build first real versions of software products at a fixed price, with the contract designed up front, working progress you can see before you pay, and code you own from the first commit. Builds start from €12,000, and I do the work myself, so there is no agency layer between you and the person writing your API. If you have a prototype that is starting to crack or a workflow that needs a real home, take a look at what I build and get in touch.

FAQ

Should my MVP use REST or GraphQL?

Use REST unless you have a concrete reason not to. It is simple, widely understood and easy to hand to the next developer. GraphQL starts to pay off when many different clients need very different shapes of data, which is rare in a first version.

Do I need to write OpenAPI documentation for an MVP?

For one core workflow, yes, and it is a small job. A single specification file lets you generate documentation and typed client code, and it gives you and the developer a shared reference before building starts. Skip the polished developer portal until you have outside developers.

How many endpoints should an MVP API have?

As few as the core workflow needs, often between 8 and 20. If you are past that, check whether you are building features users have not asked for. Every endpoint has to be secured, tested and maintained.

Can I build the API later and start with the front end?

You can, but you will pay for it. A front end that talks straight to a database or a platform's built-in backend often ends up with business rules and access control scattered across screens. A short design pass on the contract first usually makes the build faster, not slower.

What should I do if an AI-generated prototype has no real API?

Treat the prototype as a specification: list what each screen does, what data it reads and writes, and who is allowed to do it. Then design a proper contract from that list and rebuild the backend against it. The screens you validated with users stay as a reference.

Sources