5 min read931 words

Why Your Backend Should Be the Middleman: Securing Third-Party API Calls in Production

Table of Contents

  1. Overview
  2. The Flow: Double API Request
  3. What the Server Does First
  4. Sending Files to Vercel
  5. The API Response
  6. Why Two Requests and Not One
  7. The Two API Interfaces
  8. Conclusion

1. Overview

At some point in your career as a developer, you will need to call a third-party API, whether that is Stripe to process a payment, OpenAI to run a prompt, or Vercel to trigger a deployment. The instinct, especially early on, is to make that call directly from the browser. It is faster to wire up, easier to debug, and feels simpler. The problem is that it is also dangerous.

Third-party APIs require secret tokens to authenticate. Those tokens live in your code. The moment that code runs in the browser, those tokens are visible to anyone who opens the DevTools Network tab. From there, they can be copied, abused, and used to rack up charges or destroy data on your account.

The fix is a pattern called API Chaining, also known as the Backend for Frontend pattern (BFF). Instead of the browser calling the third-party API directly, it calls your own server first. Your server holds the secret token, validates the request, enforces rate limits, checks ownership, and only then forwards the call to the third-party service. The browser never sees the token. The third-party service never receives an unvalidated request.

This article walks through a real production implementation of this pattern. By the end, you will understand exactly why the extra layer exists, what it protects against, and how to structure your own server as a secure middleman between your users and any external API you depend on.

Check the project here : https://www.alainngongang.dev/projects#fastsite


2. The Flow: Double API Request

When the user clicks the deploy button, the browser fires a POST request to the server. The server sits in the middle. It receives the request from the browser, processes it, and then makes its own separate request to the Vercel API. The server is simultaneously a REST API server to the browser and a REST API client to Vercel.

image.png


3. What the Server Does First

Before any deployment can happen, the server runs through a series of validation checks in order. If any check fails, the request stops immediately and the appropriate error is returned.

  1. Auth check — no session → 401 Unauthorized
  2. Rate limit — 5 deploys per hour exceeded → 429 Too Many Requests
  3. Validate body — missing templateId or data → 400 Bad Request
  4. Env check — no VERCEL_TOKEN → return fake demo URL
  5. Portfolio ownership — if portfolioId is provided, fetch from DB and verify the user owns it → 403 Forbidden if not
  6. Project name — reuse from an existing deploymentUrl if present, otherwise generate a new one
  7. File generation — build the full Next.js file tree in memory

4. Sending Files to Vercel

The server makes a POST request to the Vercel API, sending the generated files along with the project configuration. The goal is to host and deploy the created website on Vercel's infrastructure.

const response = await fetch('https://api.vercel.com/v13/deployments', { method: 'POST', headers: { 'Authorization': `Bearer ${vercelToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: projectName, files: vercelFiles, projectSettings: { framework: 'nextjs', buildCommand: 'npm run build', installCommand: 'npm install', devCommand: 'npm run dev', outputDirectory: '.next', nodeVersion: '20.x' }, target: 'production', }), });

If this request fails, the server returns the Vercel error alongside a fake demo URL so the user experience is not completely broken.


5. The API Response

Every API response is made up of three parts: a status code, response headers, and a response body. When the Vercel deployment is created successfully, Vercel responds with the following body:

{ "id": "dpl_abc123", "url": "my-site.vercel.app", "readyState": "BUILDING" }

The server then validates the response, saves the deployment information to the database, and returns its own response to the browser:

{ "success": true, "url": "my-site.vercel.app", "deploymentId": "dpl_abc123", "readyState": "BUILDING" }

The final steps on the server side are as follows.

  • URL check — no URL in the Vercel response → throw error
  • DB update — if portfolioId exists, save deploymentUrl, deploymentId, and lastDeployedAt
  • Return 200{ success, url, projectName, deploymentId, readyState }

6. Why Two Requests and Not One

The browser cannot call Vercel directly because:

  1. VERCEL_TOKEN would be exposed to anyone who opens DevTools
  2. No rate limiting — anyone could spam deployments
  3. No auth check — anyone could deploy without being logged in

So your server acts as a secure middleman:

Browser → Your Server (guards the token) → Vercel


The Two API Interfaces

Request 1Request 2
FromBrowserYour Server
ToYour Server (/api/deploy)Vercel (api.vercel.com)
AuthBetter Auth session cookieVERCEL_TOKEN
Who built itYouVercel
Fileapi/deploy/route.tsactions/deploy.ts:127

Both are standard REST API calls. The distinction is that your server plays two roles at once: it is a server to the browser and a client to Vercel.


8. Conclusion

API Chaining is a fundamental pattern in production SaaS architecture. By placing your server in the middle, you protect sensitive credentials, enforce rate limits, validate ownership, and control exactly what reaches third-party services like Vercel. What looks like a single button click to the user is, under the hood, a carefully orchestrated sequence of two API requests built around security and reliability.

By Alain Ngongang