Introduction: The Importance of Data Validation

Welcome back! At this stage of your backend journey, your API already handles creation, retrieval, and updating of tasks. But there’s still a critical piece missing — robust, reusable validation.

Data validation ensures that:

  • Required fields are present
  • Values are the correct type and format
  • Your app doesn’t crash or store invalid data

To accomplish this at a professional level, we’ll now use a TypeScript-first schema validation library called Zod.


Why Move Beyond Manual Validation?

In earlier lessons, you wrote custom validation logic using plain TypeScript and conditional checks. While this works for simple use cases, it can quickly become:

  • Verbose and repetitive
  • Error-prone as requirements evolve
  • Difficult to maintain or reuse across endpoints

To solve this, most production backends use schema validation libraries like Zod. These libraries allow you to define strict rules for your data in a concise, declarative way — and Zod integrates seamlessly with TypeScript.

Zod lets you define "schemas" that describe exactly what a valid object looks like. It supports: Required fields, Optional fields, Default values, Nested objects, Preprocessing and transformation and Type inference (automatically generating TypeScript types from schemas)

💡 Note that Zod is pure TypeScript, and it doesn’t rely on decorators or any runtime framework, making it ideal for stateless APIs like ours.

In this lesson, you’ll replace your custom validation logic with Zod-based schemas, resulting in cleaner, safer, and more scalable backend code.


Getting Started With Zod

Zod is a TypeScript-first schema validation library. It helps you define what valid data should look like and checks incoming data against these rules.

Why use Zod?

  • It is simple and easy to use.
  • It works well with TypeScript and JavaScript.
  • It gives clear error messages when data is invalid.

Here is a basic example of a Zod schema:

  • z.object({...}) defines an object schema.
  • z.string() and z.number() set the types for each field.
  • safeParse checks whether the data matches the schema and returns an object with a success property. Calling .safeParse() on a value will return:
  • { success: true, data } if valid
  • { success: false, error } if invalid

Implementing Task Validation With Zod

Let’s define three task schemas: one for creation, one for full replacement (PUT), and one for partial updates (PATCH).

Let’s break this down:

  • title and content must be non-empty strings (min(1) means at least 1 character).
  • completed is a boolean and defaults to false if not provided.
  • dueDate is optional, but if provided, it must be a valid date string.
  • putTaskSchema: used in PUT routes, where all fields are required (full task replacement)
  • patchTaskSchema: used in PATCH routes, where all fields are optional (partial update)

Example usage:

If you try to parse invalid data:

Handling Validation Results In API Endpoints

Now, let’s see how to use these schemas in your API routes to check incoming data and respond properly.

Here’s how you can use the schema in your POST endpoint:

Explanation:

  • We use safeParse to check whether the request body matches the schema.
  • If validation fails, we return an error response with details and a 400 status code.
  • If validation passes, we create the task and return a success response.

This pattern helps ensure your API only accepts valid data and gives clear feedback when something is wrong.


Using Zod in PUT and PATCH Endpoints

Just like you did in the POST route, you can use Zod to validate the body of PUT and PATCH requests — but this time with different rules for each method.

Let’s take a look at the logic inside src/app/api/tasks/[id]/route.ts:

PUT Endpoint: All Fields Required: The PUT handler replaces the entire task, so we expect all task fields to be provided:

  • putTaskSchema validates the body and expects all fields.
  • If the input is valid and the task exists, it’s updated.
  • If the task doesn’t exist or validation fails, the API returns an error.

PATCH Endpoint: Partial Updates Allowed The PATCH handler only updates fields that the client provides:

  • patchTaskSchema uses .partial(), so it accepts any subset of task fields. This allows clients to send just what they want to change — e.g. .
Summary And Practice Preview

In this lesson, you learned:

  • Why data validation is important for production-ready APIs
  • How to use Zod to define and check schemas for your data
  • How to handle validation results in your Next.js API endpoints

With these skills, you are ready to practice adding and using validation in your own API routes. In the next exercises, you will get hands-on experience with Zod and see how it helps keep your application safe and reliable.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal