API Response Formatter

The API Response Formatter component provides a consistent, predictable, and type-safe response structure for Express-based APIs.

It enforces a unified response contract across your entire backend, improving:

  • Client-side reliability
  • API readability
  • Error handling consistency
  • Developer experience

This component is designed to work seamlessly with:

  • Async Handler
  • ApiError
  • Centralized error middleware
  • Frontend API clients

Installation Guide

npx servercn-cli add response-formatter

The Problem It Solves

In many Express applications, responses quickly become inconsistent:

res.json(data);
res.status(201).send(user);
res.status(400).json({ error: "Invalid input" });

Basic Implementation

MVC: src/utils/api-response.ts

Feature: src/shared/utils/api-response.ts

import { STATUS_CODES, StatusCode } from "../constants/status-codes";
import type { Response } from "express";
 
type ApiResponseParams<T> = {
  success: boolean;
  message: string;
  statusCode: StatusCode;
  data?: T | null;
  errors?: unknown;
};
 
export class ApiResponse<T = unknown> {
  public readonly success: boolean;
  public readonly message: string;
  public readonly statusCode: StatusCode;
  public readonly data?: T | null;
  public readonly errors?: unknown;
 
  constructor({
    success,
    message,
    statusCode,
    data = null,
    errors
  }: ApiResponseParams<T>) {
    this.success = success;
    this.message = message;
    this.statusCode = statusCode;
    this.data = data;
    this.errors = errors;
  }
 
  send(res: Response): Response {
    return res.status(this.statusCode).json({
      success: this.success,
      message: this.message,
      statusCode: this.statusCode,
      ...(this.data !== undefined && { data: this.data }),
      ...(this.errors !== undefined && { errors: this.errors })
    });
  }
 
  static Success<T>(
    res: Response,
    message: string,
    data?: T,
    statusCode: StatusCode = STATUS_CODES.OK
  ): Response {
    return new ApiResponse<T>({
      success: true,
      message,
      data,
      statusCode
    }).send(res);
  }
 
  static ok<T>(res: Response, message = "OK", data?: T) {
    return ApiResponse.Success(res, message, data, STATUS_CODES.OK);
  }
 
  static created<T>(res: Response, message = "Created", data?: T) {
    return ApiResponse.Success(res, message, data, STATUS_CODES.CREATED);
  }
}
 
/*
 * Usage:
 * ApiResponse.ok(res, "OK", data);
 * ApiResponse.created(res, "Created", data);
 */

Usage Example

import { Request, Response } from "express";
import { ApiResponse } from "../utils/api-response";
 
export async function healthCheck(_req: Request, res: Response) {
  return ApiResponse.ok(res, "Service is healthy");
}

Response

{
  "success": true,
  "message": "Service is healthy",
  "statusCode": 200
}

File & Folder Structure

Loading files...

Installation

npx servercn-cli add response-formatter