Documentation Index
Fetch the complete documentation index at: https://robintail-express-zod-api-69.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The ez object provides specialized Zod schemas for common API patterns like dates, file uploads, forms, and raw data.
import { ez } from "express-zod-api";
import { z } from "zod";
Date Schemas
ez.dateIn()
Accepts ISO date strings and provides Date objects to your handler.
const endpoint = defaultEndpointsFactory.build({
input: z.object({
startDate: ez.dateIn(),
endDate: ez.dateIn({ examples: ["2024-12-31"] }),
}),
handler: async ({ input }) => {
// input.startDate and input.endDate are Date objects
const days = daysBetween(input.startDate, input.endDate);
return { days };
},
});
Supported formats:
2021-12-31T23:59:59.000Z
2021-12-31T23:59:59Z
2021-12-31T23:59:59
2021-12-31
ez.dateOut()
Accepts Date objects from your handler and returns ISO strings in responses.
const endpoint = defaultEndpointsFactory.build({
output: z.object({
createdAt: ez.dateOut(),
updatedAt: ez.dateOut({ examples: ["2024-01-01T00:00:00Z"] }),
}),
handler: async () => {
return {
createdAt: new Date(),
updatedAt: new Date("2024-01-01"),
};
},
});
File Upload
ez.upload()
Handles file uploads with multipart/form-data.
const uploadEndpoint = defaultEndpointsFactory.build({
method: "post",
input: z.object({
avatar: ez.upload(),
document: ez.upload(),
}),
output: z.object({ success: z.boolean() }),
handler: async ({ input }) => {
// input.avatar: { name, mv(), mimetype, data, size, etc }
await input.avatar.mv(`/uploads/${input.avatar.name}`);
return { success: true };
},
});
File object properties:
MIME type (e.g., “image/png”)
Move file to destination: mv(path: string) => Promise<void>
True if file exceeded size limit
Handles URL-encoded form data (application/x-www-form-urlencoded).
const formEndpoint = defaultEndpointsFactory.build({
method: "post",
input: ez.form({
name: z.string().min(1),
email: z.string().email(),
subscribe: z.enum(["true", "false"]).transform(v => v === "true"),
}),
output: z.object({ success: z.boolean() }),
handler: async ({ input }) => {
await saveContact(input);
return { success: true };
},
});
Raw Data
ez.raw()
Accepts raw request body as Buffer for binary data.
import { ez } from "express-zod-api";
const rawEndpoint = defaultEndpointsFactory.build({
method: "post",
input: ez.raw({
examples: [{ data: Buffer.from("example").toString("base64") }],
}),
output: z.object({ length: z.number() }),
handler: async ({ input: { data } }) => {
// data is a Buffer
return { length: data.length };
},
});
ez.buffer()
For documenting binary responses in OpenAPI.
const fileResultHandler = new ResultHandler({
positive: { schema: ez.buffer(), mimeType: "application/pdf" },
// ...
});
ez.paginated()
Creates reusable pagination schemas.
import { ez } from "express-zod-api";
import { z } from "zod";
const pagination = ez.paginated({
style: "offset", // or "cursor"
itemSchema: z.object({
id: z.number(),
name: z.string(),
}),
itemsName: "users",
maxLimit: 100,
defaultLimit: 20,
});
const listUsers = defaultEndpointsFactory.build({
input: pagination.input,
output: pagination.output,
handler: async ({ input: { limit, offset } }) => {
const users = await db.users.find().limit(limit).skip(offset);
const total = await db.users.count();
return { users, total, limit, offset };
},
});
Offset-based (limit/offset):
// Input: { limit?: number, offset?: number }
// Output: { items: T[], total: number, limit: number, offset: number }
Cursor-based (limit/cursor):
// Input: { limit?: number, cursor?: string }
// Output: { items: T[], nextCursor: string | null, limit: number }
Complete Example
import { defaultEndpointsFactory, ez } from "express-zod-api";
import { z } from "zod";
const createEventEndpoint = defaultEndpointsFactory.build({
method: "post",
input: z.object({
title: z.string().min(1).max(200),
description: z.string(),
startDate: ez.dateIn(),
endDate: ez.dateIn(),
image: ez.upload().optional(),
}),
output: z.object({
id: z.string(),
createdAt: ez.dateOut(),
imageUrl: z.string().url().nullable(),
}),
handler: async ({ input }) => {
let imageUrl = null;
if (input.image) {
const filename = `${uuid()}.${ext(input.image.name)}`;
await input.image.mv(`./uploads/${filename}`);
imageUrl = `https://cdn.example.com/${filename}`;
}
const event = await db.events.create({
title: input.title,
description: input.description,
startDate: input.startDate,
endDate: input.endDate,
imageUrl,
});
return {
id: event.id,
createdAt: event.createdAt,
imageUrl,
};
},
});
See Also
Dates
Working with dates in detail
File Uploads
Complete file upload guide
Pagination
Pagination patterns
Raw Data
Handle binary data