Adding API Documentation with Swagger to Your Node.js API
This tutorial builds on our rate-limited API by adding comprehensive API documentation using Swagger/OpenAPI. We'll implement interactive documentation that helps developers understand and test your API endpoints.
Prerequisites
- Completed Parts 1-4 of the tutorial
- Basic understanding of REST API concepts
- Node.js and npm installed
Project Setup
Install the required dependencies:
npm install swagger-ui-express swagger-jsdoc yaml
Updated Project Structure
Add these new files to your project:
books-api/
├── src/
│ ├── config/
│ │ ├── database.js
│ │ ├── auth.js
│ │ ├── rateLimiter.js
│ │ └── swagger.js
│ ├── docs/
│ │ ├── swagger.yaml
│ │ ├── components.yaml
│ │ ├── paths/
│ │ │ ├── auth.yaml
│ │ │ └── books.yaml
│ │ └── schemas/
│ │ ├── Book.yaml
│ │ └── User.yaml
│ └── server.js
Environment Setup
Update your .env
file:
API_VERSION=1.0.0
API_TITLE=Books API
API_DESCRIPTION=RESTful API for managing books
API_SERVER_URL=http://localhost:3000
Swagger Configuration
Create src/config/swagger.js
:
const swaggerJsdoc = require('swagger-jsdoc');
const yaml = require('yaml');
const fs = require('fs');
const path = require('path');
// Read individual YAML files
const readYamlFile = (filePath) => {
const fileContents = fs.readFileSync(filePath, 'utf8');
return yaml.parse(fileContents);
};
// Swagger definition
const swaggerDefinition = {
openapi: '3.0.0',
info: {
title: process.env.API_TITLE,
version: process.env.API_VERSION,
description: process.env.API_DESCRIPTION,
license: {
name: 'MIT',
url: 'https://opensource.org/licenses/MIT',
},
contact: {
name: 'API Support',
email: 'support@example.com',
},
},
servers: [
{
url: process.env.API_SERVER_URL,
description: 'Development server',
},
],
components: {
securitySchemes: {
BearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
},
schemas: {
Book: readYamlFile(path.join(__dirname, '../docs/schemas/Book.yaml')),
User: readYamlFile(path.join(__dirname, '../docs/schemas/User.yaml')),
},
},
};
// Swagger options
const options = {
swaggerDefinition,
apis: [
'./src/routes/*.js',
'./src/docs/paths/*.yaml'
],
};
const swaggerSpec = swaggerJsdoc(options);
module.exports = swaggerSpec;
Schema Definitions
Create src/docs/schemas/Book.yaml
:
type: object
properties:
_id:
type: string
format: objectId
description: The auto-generated id of the book
title:
type: string
description: The title of the book
author:
type: string
description: The author of the book
isbn:
type: string
description: ISBN number of the book
publishedDate:
type: string
format: date
description: Publication date of the book
genre:
type: string
description: Genre of the book
description:
type: string
description: Brief description of the book
required:
- title
- author
- isbn
Create src/docs/schemas/User.yaml
:
type: object
properties:
_id:
type: string
format: objectId
description: The auto-generated id of the user
email:
type: string
format: email
description: User's email address
name:
type: string
description: User's full name
role:
type: string
enum: [user, editor, admin]
description: User's role in the system
createdAt:
type: string
format: date-time
description: Account creation timestamp
required:
- email
- name
- role
API Path Documentation
Create src/docs/paths/books.yaml
:
/api/books:
get:
tags:
- Books
summary: Get all books
description: Retrieve a list of all books with optional filtering
parameters:
- in: query
name: genre
schema:
type: string
description: Filter books by genre
- in: query
name: author
schema:
type: string
description: Filter books by author
responses:
200:
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Book'
429:
description: Too many requests
500:
description: Server error
post:
tags:
- Books
summary: Add a new book
description: Add a new book to the database
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
responses:
201:
description: Book created successfully
400:
description: Invalid input
401:
description: Unauthorized
429:
description: Too many requests
Create src/docs/paths/auth.yaml
:
/api/auth/login:
post:
tags:
- Authentication
summary: User login
description: Authenticate user and receive JWT token
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
format: email
password:
type: string
format: password
required:
- email
- password
responses:
200:
description: Login successful
content:
application/json:
schema:
type: object
properties:
token:
type: string
user:
$ref: '#/components/schemas/User'
401:
description: Invalid credentials
429:
description: Too many login attempts
Route Documentation
Update your route files to include JSDoc comments. Example for src/routes/books.js
:
const express = require('express');
const router = express.Router();
/**
* @swagger
* tags:
* name: Books
* description: Book management endpoints
*/
/**
* @swagger
* /api/books/{id}:
* get:
* tags: [Books]
* summary: Get a book by ID
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: Book ID
* responses:
* 200:
* description: Success
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* 404:
* description: Book not found
*/
router.get('/:id', getBook);
// Other routes...
Updated Server File
Update src/server.js
:
const express = require('express');
const swaggerUi = require('swagger-ui-express');
const swaggerSpec = require('./config/swagger');
const { basicRateLimiter } = require('./middleware/rateLimiter');
const app = express();
// Swagger UI setup
app.use(
'/api-docs',
swaggerUi.serve,
swaggerUi.setup(swaggerSpec, {
explorer: true,
customSiteTitle: 'Books API Documentation',
customCss: '.swagger-ui .topbar { display: none }',
swaggerOptions: {
docExpansion: 'none',
persistAuthorization: true,
filter: true,
},
})
);
// Rate limit the documentation
app.use('/api-docs', basicRateLimiter);
// Existing middleware and routes...
Custom Documentation Customization
Create a custom documentation template:
const customOptions = {
customCssUrl: '/custom-swagger.css',
customJs: '/custom-swagger.js',
customfavIcon: '/favicon.ico',
};
// Custom CSS for documentation
app.get('/custom-swagger.css', (req, res) => {
res.sendFile(path.join(__dirname, 'docs/styles/swagger.css'));
});
Documentation Security
Implement documentation access control:
const docsAuthMiddleware = (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (process.env.NODE_ENV === 'production' && apiKey !== process.env.DOCS_API_KEY) {
return res.status(401).json({ error: 'Unauthorized access to documentation' });
}
next();
};
app.use('/api-docs', docsAuthMiddleware);
Testing Documentation
Test your API documentation using these curl commands:
# Get documentation JSON
curl http://localhost:3000/api-docs.json
# Test documentation with API key
curl -H "X-API-KEY: your_api_key" http://localhost:3000/api-docs
Best Practices Implemented
Organization
- Modular documentation structure
- Separate schema definitions
- Route-specific documentation files
- Environment-based configuration
Security
- Protected documentation access
- Rate-limited documentation endpoints
- Environment-specific settings
- Authentication examples
User Experience
- Interactive API testing
- Clear parameter descriptions
- Request/response examples
- Error documentation
Maintenance
- Version control
- Easy updates
- Consistent formatting
- Reusable components
Next Steps
To enhance your API further:
Conclusion
You now have comprehensive API documentation that:
- Helps developers understand your API
- Provides interactive testing
- Maintains security
- Scales with your API
- Follows OpenAPI standards
Remember to:
- Keep documentation updated
- Test documentation regularly
- Gather user feedback
- Monitor documentation usage
- Update examples as needed
The next tutorial will cover implementing automated testing for your API endpoints.
Related Posts
6 min read
The Model Context Protocol (MCP) has emerged as one of the most significant developments in AI technology in 2025. Launched by Anthropic in November 2024, MCP is an open standard designed to bridge AI...
5 min read
APIs (Application Programming Interfaces) are the backbone of modern digital applications. They allow different software systems to communicate, exchange data, and collaborate seamlessly. As businesse...