DEV Community

Kiran Krishnan
Kiran Krishnan

Posted on • Originally published at kirandev.com

How to validate Next.js API routes using Zod

In this article, you'll learn how to validate Next.js API routes using Zod.

Let's create a new file called /api/users.ts. The API endpoint /api/users will accept POST requests with a JSON body.

import type { NextApiRequest, NextApiResponse } from "next";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { method } = req;

  if (method !== "POST") {
    res.setHeader("Allow", ["GET", "POST"]);
    res.status(405).json({
      error: { message: `Method ${method} Not Allowed` },
    });
  }

  // Validate the request body

  return res.status(200).json({ message: "Success" });
}
Enter fullscreen mode Exit fullscreen mode

Install Zod

Let's install Zod using npm.

npm install zod
Enter fullscreen mode Exit fullscreen mode

Create the schema

Next, we will create the schema to represent the request body.

import { z } from "zod";

const schema = z.object({
  name: z.string(),
  email: z.string(),
  zipcode: z.number().min(5).max(5),
  subcribe: z.boolean().optional(),
});
Enter fullscreen mode Exit fullscreen mode

The sample request body will look like this:

{
  "name": "Kiran",
  "email": "kiran@example.com",
  "zipcode": "12345",
  "subcribe": true // optional
}
Enter fullscreen mode Exit fullscreen mode

Validate the request body

Next step is to validate the request body using the above schema. We will use the safeParse method to validate.

const response = schema.safeParse(req.body);

// If the request body is invalid, return a 400 error with the validation errors
if (!response.success) {
  const { errors } = response.error;

  return res.status(400).json({
    error: { message: "Invalid request", errors },
  });
}

// Now you can safely use the data to create a user
const { name, email, zipcode, subcribe } = response.data;
Enter fullscreen mode Exit fullscreen mode

If the request validation fails, we will return a 400 status code with the validation errors. You can access the validation errors using the errors property on the JSON response.

Here is how the response will look like if the request body is invalid:

{
  "error": {
    "message": "Invalid request",
    "errors": [
      {
        "validation": "email",
        "code": "invalid_string",
        "message": "Invalid email",
        "path": ["email"]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

You can use the library Zod Error to convert the validation errors to a more readable format.

Here is the full code for the API endpoint:

import type { NextApiRequest, NextApiResponse } from "next";
import { z } from "zod";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { method } = req;

  if (method !== "POST") {
    return res.status(405).json({
      error: { message: `Method ${method} Not Allowed` },
    });
  }

  const schema = z.object({
    name: z.string(),
    email: z.string().email(),
    zipcode: z.string().min(5).max(5),
    subcribe: z.boolean().optional(),
  });

  const response = schema.safeParse(req.body);

  if (!response.success) {
    const { errors } = response.error;

    return res.status(400).json({
      error: { message: "Invalid request", errors },
    });
  }

  const { name, email, zipcode, subcribe } = response.data;

  return res.status(200).json({ message: "Success" });
}
Enter fullscreen mode Exit fullscreen mode

Here is the curl command to test the API endpoint:

curl --request POST \
  --url http://localhost:3000/api/users \
  -H 'Content-Type: application/json' \
  --data '{"name":"Kiran","email":"kiran@example.com","zipcode":"12345","subcribe":false}'
Enter fullscreen mode Exit fullscreen mode

If you're planning to build a SaaS app, then you might be interested in NextAPI. NextAPI is a Next.js RESTful API Starter for building SaaS Apps. NextAPI can handle the heavy lifting for common SaaS features such as authentication, team management, invites, subscriptions, and more.

Top comments (0)