API Contracts – The Blood Pact Between FE & BE

Faiaz KhanFaiaz Khan
3 min read

APIs aren’t just about fetching data.
They’re about trust. Mutual understanding. Respect. And sometimes… brutal betrayal.

That trust is encoded in the API contract — the agreed structure of requests and responses between frontend and backend.

Today we’re decoding:

  • What an API contract actually is

  • How to survive without one (but maybe don’t)

  • Why types are your BFF

  • How to make this pact less painful


So… What’s an API Contract?

An API contract is the shared agreement between frontend and backend on:

  • What requests can be made

  • What structure the responses will have

  • What status codes are used

  • And what to expect on errors

It’s like a prenup for your components and your data.


Why It Matters

If frontend expects:

{ "name": "Faiaz", "avatar": "url", "isOnline": true }

…but backend sends:

{ "full_name": "Faiaz", "profile_img": "url" }

You don’t just get a broken UI — you get a broken soul.

The mismatch between expectations and reality is a silent killer of productivity and sanity.


Real-World Consequences of a Bad Contract

IssuePain
Fields missing/renamedBreaks the UI
Wrong typesundefined is not a function
No docs or samplesGuesswork hell
Backend changes silentlyProduction bugs outta nowhere
Status code rouletteCan’t even show proper error UX

How to Make the Pact Stronger

1. Use OpenAPI/Swagger (aka. actual docs)

Machine-readable, dev-readable. Best of both worlds.

You’ll know what endpoints exist, their params, response shapes, and error formats — like a menu with pictures.


2. Define Types (TS, Zod, Yup)

If the response lies, your app knows.

type User = {
  id: string;
  name: string;
  avatar: string;
  isOnline: boolean;
}

Then use validators like Zod to make sure the backend ain't gaslighting you.

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  avatar: z.string().url(),
  isOnline: z.boolean(),
});

3. Create Shared Types Between FE & BE

Sounds like magic? Use tools like:

  • tRPC

  • TypeScript SDK generators

  • Or shared @types package in monorepos

So backend changes = frontend gets updated types automatically.


4. Start Mocking Early

Don’t wait for backend to finish — use:

  • Mock Service Worker (MSW)

  • JSON Server

  • Swagger-generated mock servers

Helps FE and BE work in parallel like real adults.


Common Frontend Struggles (and Fixes)

ProblemFix
Response shape changedUse type validation (Zod, Yup)
Can’t understand backend responseAsk for Swagger or example payload
Error response structure variesStandardize error model with backend
Unclear field types (null vs string?)Use Partial<T> or defensive parsing
API updates silentlyUse semantic versioning + changelogs

Team Agreements That Save Lives

  • Agree on error shapes ({ code, message })

  • Document every new endpoint (even WIP ones)

  • Set up a shared Postman collection or Swagger URL

  • Never change response shape in prod without notice

  • Use versioned endpoints (/v1/users) when making breaking changes


Final Thoughts

APIs are the bridge between frontend dreams and backend logic.
But without a solid contract, it’s just cross-origin chaos.

So the next time someone says:

"Just hit the endpoint and see what comes back."

You reply:

"Cool, and should I also roll the dice while I’m at it?"

Be smart. Type your responses. Mock early. Validate often.
Make the contract sacred.


📚 This is Awaiting Response(),
Where we don’t just fetch data — we establish healthy boundaries.

Next up:
Debounce, Throttle, Cancel – Optimizing API Calls Like a Pro

Let’s save your UI from making 300 network requests per keystroke 😎

0
Subscribe to my newsletter

Read articles from Faiaz Khan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Faiaz Khan
Faiaz Khan

Hey! I'm Faiaz — a frontend developer who loves writing clean, efficient, and readable code (and sometimes slightly chaotic code, but only when debugging). This blog is my little corner of the internet where I share what I learn about React, JavaScript, modern web tools, and building better user experiences. When I'm not coding, I'm probably refactoring my to-do list or explaining closures to my cat. Thanks for stopping by — hope you find something useful or mildly entertaining here.