We're excited to share that all API routes in Dub.co now come equipped with a powerful request validation powered by Zod.
This has allowed us to catch any schema errors in run-time, providing a better developer experience for our API consumers.
In this post, we're going to take a look at how we integrated Zod to make sure API requests are validated properly.
The Problem
Have you ever accidentally sent the wrong data to the server, and the server responded with a 500 error without any helpful message?
This is a common problem when the server doesn't properly validate requests. It can be frustrating for developers who are trying to integrate with the API.
This is what we aim to solve using Zod.
What is Zod?
Zod is a TypeScript-first schema declaration and validation library. Like TypeScript catches type errors at compile time, Zod catches schema errors at runtime.
Why Zod?
Runtime validation ensures the request body and query parameters are in the expected format and structure.
Doing this manually is error-prone and not developer-friendly. This quickly becomes a maintenance nightmare as the number of route handlers grows.
This is where Zod comes into play. Zod is designed to be as developer-friendly as possible. Zod allows us to define the schema representing the request body and validate them at runtime.
Define the schema
Let's look at how we applied zod validation to the route handler responsible for creating the short links, the most critical route handler in the entire codebase.
Here, createLinkBodySchema
defines the expected shape of the request body.
The describe
method is used to provide a description for each field. Later we'll see how this description is used to generate the OpenAPI schema.
The schema above was truncated for brevity. You can refer to the full schema here.
Validate the request body
Next, we use the schema createLinkBodySchema
to validate the request body in the route handler.
Whenever the API receives a request, it checks the request body against the schema to ensure that all the required data is present. This has proved beneficial in a number of ways.
- Handle unexpected or invalid request body.
- Validate the inputs for expected format and shape.
- Provide a better developer experience by returning a friendly error message.
Returning user-friendly error messages
Zod errors are difficult for the end-users to understand. Hence, we must convert the Zod error to a user-friendly error message.
zod-error
comes in handy to convert the Zod error to an easy-to-understand error message. Here is a quick example of how we use zod-error
in our codebase.
zod-error
comes with a number of options to customize the error message. You can find the complete list of options here.
fromZodError
formats Zod Issues into a error message string that can be consumed by various clients.
It converts an array of Zod Issues that look like this:
...into this:
This error message can be customized to suit your needs. We're still improving it to make it more user-friendly.
Auto-generating OpenAPI spec from Zod schema
We understand that manually updating the OpenAPI specification is tedious and often leads to errors and inconsistencies.
In most cases, the OpenAPI specification is not in sync with the actual request schema, making it a significant pain point for developers.
Fortunately, the Zod ecosystem has come up with a solution to this problem.
The zod-openapi
package generates the OpenAPI specification automatically from the Zod schema, ensuring that the OpenAPI specification is always up-to-date.
It has been a game-changer for us as it has significantly reduced the maintenance overhead of updating the OpenAPI specification.
If you're interested in learning more about how this works, you can check out the code that generates the OpenAPI specification from the Zod schema here.
Mintlify utilises this OpenAPI specification to produce the visually appealing API documentation that enables users to fully comprehend the functionality of our platform.
Conclusion
Schema validation is an essential aspect of API development, as it ensures the consistency and integrity of data.
Zod has made this process more manageable by providing a simple and intuitive way to define and validate the schema.
Even though we are in the early stages of using Zod in our codebase, we have already noticed an improvement in the developer experience.
Furthermore, it has helped reduce the maintenance overhead of updating the OpenAPI specfification.
We're excited to continue using the powerful combination of Zod and TypeScript at Dub.
Our codebase is fully open-source, so feel free to check it out and learn more about how we use Zod in our API route handlers.