OpenAPI 3.0 / Swagger Documentation
An API without documentation is an API that only its author can use. OpenAPI 3.0 is the industry-standard specification for describing REST APIs: it defines your endpoints, request parameters, request bodies, response shapes, authentication schemes, and error formats in a machine-readable YAML or JSON format. From an OpenAPI spec, tools can generate interactive documentation, client SDKs in any language, mock servers, and automated tests. In Node.js, swagger-jsdoc generates the spec from JSDoc comments in your source code, and swagger-ui-express serves the interactive Swagger UI.
Defining the OpenAPI Spec with swagger-jsdoc
swagger-jsdoc reads JSDoc comments annotated with @openapi (or @swagger) tags from your route files and assembles them into a complete OpenAPI 3.0 document. The base spec (info, servers, components/schemas, securitySchemes) is defined once in a central config. Route-level docs are co-located with the route code, keeping documentation and implementation together.
npm install swagger-jsdoc swagger-ui-express// config/swagger.js
const swaggerJsdoc = require('swagger-jsdoc');
const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Cricket API',
version: '1.0.0',
description: 'Node.js & Express Backend — SkillVeris Course 4 Example API',
contact: { name: 'API Support', email: '[email protected]' }
},
servers: [
{ url: 'http://localhost:3000', description: 'Development' },
{ url: 'https://api.myapp.com', description: 'Production' }
],
components: {
securitySchemes: {
bearerAuth: {
type: 'http', scheme: 'bearer', bearerFormat: 'JWT'
}
},
schemas: {
Product: {
type: 'object',
required: ['name', 'price'],
properties: {
id: { type: 'string', example: '64abc123' },
name: { type: 'string', example: 'Cricket Bat' },
price: { type: 'number', example: 120.00 },
category: { type: 'string', example: 'equipment' }
}
},
Error: {
type: 'object',
properties: {
error: { type: 'string', example: 'Not found' }
}
}
}
}
},
apis: ['./routes/**/*.js'] // paths to files with @openapi annotations
};
module.exports = swaggerJsdoc(options);Annotating Routes with JSDoc
Each route gets a JSDoc block with @openapi tags describing its method, path, parameters, request body, and all possible responses. The descriptions appear verbatim in the Swagger UI, so write them for your API consumers, not for yourself.
// routes/products.js
/**
* @openapi
* /api/v1/products:
* get:
* summary: List all products
* tags: [Products]
* parameters:
* - in: query
* name: page
* schema: { type: integer, default: 1 }
* description: Page number
* - in: query
* name: limit
* schema: { type: integer, default: 10, maximum: 100 }
* description: Items per page
* - in: query
* name: category
* schema: { type: string }
* description: Filter by category
* responses:
* 200:
* description: Paginated product list
* content:
* application/json:
* schema:
* type: object
* properties:
* data:
* type: array
* items:
* $ref: '#/components/schemas/Product'
* meta:
* type: object
* properties:
* total: { type: integer }
* page: { type: integer }
* pages: { type: integer }
*/
router.get('/', asyncHandler(getProducts));
/**
* @openapi
* /api/v1/products:
* post:
* summary: Create a new product
* tags: [Products]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Product'
* responses:
* 201:
* description: Product created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Product'
* 401:
* description: Unauthenticated
* 403:
* description: Forbidden
* 422:
* description: Validation error
*/
router.post('/', authenticate, authorize('write:products'), asyncHandler(createProduct));