Lesson 38 of 50 – API Validation in Express.js
76% Completed
76%

API Validation in Express.js

Learn how to validate incoming API data, check required fields, verify data types, validate email addresses, and return useful error messages before processing requests.

In this lesson: You will learn why validation is important, how to validate request bodies and route parameters, how to handle invalid data, and how to use the express-validator package.

1. What Is API Validation?

API validation means checking data received from a client before the server accepts or processes it.

For example, when a student registers, the API may need to check:

  • The student's name is provided.
  • The email address has a valid format.
  • The age is a valid number.
  • The course name is not empty.
  • The submitted values meet the application's rules.
Validation Process
Client Sends Data
↓
Validate Input

Check required fields and data types

↓
Valid Data

Continue processing the request

Invalid Data

Return a validation error

2. Why Is Validation Important?

Reason Explanation
Data quality Prevents incomplete or incorrectly formatted information.
Security Helps reject unexpected or malicious input.
Consistency Ensures data follows application rules.
Useful errors Explains why a request was rejected.
Reliable APIs Reduces problems caused by invalid data.
Important: Validation is not a replacement for authentication, authorization, database constraints, or safe database queries. A secure API often needs all of these controls.

3. Create an API Validation Project

Create a new Node.js project.

mkdir validation-api
cd validation-api
npm init -y
npm install express

Create a file named app.js.

4. Validate Required Fields Manually

The simplest approach is to check the request body inside the route handler.

app.js
const express = require('express');

const app = express();

app.use(express.json());

app.post('/api/students', (req, res) => {
    const { name, course } = req.body;

    if (!name || !course) {
        return res.status(400).json({
            message: 'Name and course are required'
        });
    }

    res.status(201).json({
        message: 'Student data is valid',
        student: {
            name: name,
            course: course
        }
    });
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

Valid request body:

{
    "name": "Amit",
    "course": "Node.js"
}

Example successful response:

{
    "message": "Student data is valid",
    "student": {
        "name": "Amit",
        "course": "Node.js"
    }
}

Invalid request body:

{
    "name": ""
}

Example error response:

{
    "message": "Name and course are required"
}
This first example checks whether fields are present. It does not yet verify their types or whether they contain only whitespace.

5. Validate Data Types and Empty Strings

A field can exist but still contain an invalid value. For example, a name should be a non-empty string rather than a number or an array.

Example: Stronger Manual Validation
app.post('/api/students', (req, res) => {
    const { name, course } = req.body;

    if (
        typeof name !== 'string' ||
        name.trim() === ''
    ) {
        return res.status(400).json({
            message: 'Name must be a non-empty string'
        });
    }

    if (
        typeof course !== 'string' ||
        course.trim() === ''
    ) {
        return res.status(400).json({
            message: 'Course must be a non-empty string'
        });
    }

    res.status(201).json({
        message: 'Student validated successfully',
        student: {
            name: name.trim(),
            course: course.trim()
        }
    });
});

The trim() method removes whitespace from the beginning and end of a string.

For example, a name containing only spaces is rejected.

6. Validate Email Addresses

Email addresses should be checked before accepting registration data. The following example demonstrates a basic format check.

Example: Basic Email Validation
function isValidEmail(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

app.post('/api/register', (req, res) => {
    const { name, email } = req.body;

    if (typeof name !== 'string' || !name.trim()) {
        return res.status(400).json({
            message: 'Name is required'
        });
    }

    if (
        typeof email !== 'string' ||
        !isValidEmail(email)
    ) {
        return res.status(400).json({
            message: 'Please provide a valid email format'
        });
    }

    res.status(201).json({
        message: 'Registration data is valid',
        name: name.trim(),
        email: email
    });
});

Example valid format:

student@example.com

Example invalid format:

student-example.com
This regular expression checks a basic email format only. It does not prove that the email address exists or that the user owns it. Email verification requires a separate verification process.

7. Validate Numbers and Ranges

When receiving an age or another numeric value, check its type and range instead of assuming the client sent a number.

Example: Validate Student Age
app.post('/api/student-age', (req, res) => {
    const { age } = req.body;

    if (
        typeof age !== 'number' ||
        !Number.isInteger(age) ||
        age < 5 ||
        age > 100
    ) {
        return res.status(400).json({
            message: 'Age must be an integer from 5 to 100'
        });
    }

    res.json({
        message: 'Age is valid',
        age: age
    });
});

Valid JSON:

{
    "age": 20
}

Invalid JSON value:

{
    "age": "twenty"
}

JSON number values and JSON string values are different. The example expects age to be a number.

8. Validate Route Parameters

Route parameters may also contain invalid values. For example, a student ID is expected to be a positive integer.

Example: Validate Student ID
app.get('/api/students/:id', (req, res) => {
    const id = Number(req.params.id);

    if (!Number.isInteger(id) || id <= 0) {
        return res.status(400).json({
            message: 'Student ID must be a positive integer'
        });
    }

    res.json({
        message: 'Student ID is valid',
        id: id
    });
});

Example URL:

http://localhost:3000/api/students/101

Example response:

{
    "message": "Student ID is valid",
    "id": 101
}

9. Use express-validator

For larger applications, a validation library can help keep validation rules organized. express-validator provides validation and sanitization tools for Express requests.

Install the package:

npm install express-validator
Example: Validate Student Registration
const express = require('express');

const {
    body,
    validationResult
} = require('express-validator');

const app = express();

app.use(express.json());

app.post(
    '/api/students',
    [
        body('name')
            .isString()
            .withMessage('Name must be a string')
            .bail()
            .trim()
            .notEmpty()
            .withMessage('Name is required'),

        body('email')
            .isEmail()
            .withMessage('Enter a valid email address'),

        body('age')
            .isInt({ min: 5, max: 100 })
            .withMessage('Age must be an integer from 5 to 100')
    ],
    (req, res) => {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            return res.status(400).json({
                errors: errors.array()
            });
        }

        res.status(201).json({
            message: 'Student data is valid',
            student: req.body
        });
    }
);

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

The validation rules run before the final route handler. If a rule fails, validationResult(req) provides the validation errors.

10. Test the Validation API

Run the application and use Postman to send a POST request.

node app.js

Request URL:

POST http://localhost:3000/api/students

In Postman, select Body → raw → JSON and send:

{
    "name": "Amit",
    "email": "amit@example.com",
    "age": 20
}

Example successful response:

{
    "message": "Student data is valid",
    "student": {
        "name": "Amit",
        "email": "amit@example.com",
        "age": 20
    }
}

Now test with invalid data:

{
    "name": "",
    "email": "invalid-email",
    "age": 150
}

The API should return HTTP status code 400 with validation errors describing the invalid fields.

11. Common Validation Errors

Problem Solution
Required field is missing Check that the field exists and is not empty.
Number received as a string Validate the expected data type or explicitly parse an accepted input format.
Invalid email address Use an email validation rule.
Invalid route ID Check that the ID is a positive integer.
Missing req.body data Register the correct body-parsing middleware before the route.
Unexpected or malformed JSON Return an appropriate client error and avoid processing invalid data.

12. Practical Assignment

Assignment: Student Registration Validation API

Create an Express API with the following requirements:

  1. Create a POST route named /api/register.
  2. Require a student name.
  3. Validate the email address.
  4. Require an age between 5 and 100.
  5. Require a course name.
  6. Return status code 400 when validation fails.
  7. Return status code 201 when the submitted data is valid.
  8. Use express-validator to organize the validation rules.
  9. Test valid and invalid requests using Postman.
Lesson Summary: You learned manual input validation, checking required fields, validating data types and ranges, validating email formats, validating route parameters, and using express-validator.

Test Your Knowledge – MCQ Quiz

Select the correct answer for each question.

1. Why do we validate API input?
2. Which package provides validation tools for Express requests?
3. Which HTTP status code commonly indicates invalid request data?