Validate :id and Other Path Params
Params Schemas
schema.params validates URL path parameters and, with type coercion, turns the string `:id` into a real number before your handler sees it.
What you'll learn
- Declare the params shape with JSON Schema
- Coerce id to integer or uuid format
- Reject malformed paths with 400 automatically
Path params arrive as strings — /users/42 gives you '42'. A params schema validates the
shape and coerces values into the right runtime type.
Coercing :id to a Number
app.get('/users/:id', {
schema: {
params: {
type: 'object',
required: ['id'],
properties: {
id: { type: 'integer', minimum: 1 },
},
},
},
handler: async (req) => {
// req.params.id is now `number`, not `string`
return await db.users.find(req.params.id);
},
}); Fastify enables Ajv coercion for params and querystring by default, so '42' becomes the
number 42. A request like /users/abc returns 400 Bad Request before the handler runs.
Multiple Params
app.get('/orgs/:orgId/projects/:projectId', {
schema: {
params: {
type: 'object',
required: ['orgId', 'projectId'],
properties: {
orgId: { type: 'string', format: 'uuid' },
projectId: { type: 'string', pattern: '^[a-z0-9-]+$' },
},
},
},
handler: async (req) => {
const { orgId, projectId } = req.params;
return getProject(orgId, projectId);
},
}); When the URL Doesn’t Match
If you skip the schema, params are always strings — you will end up writing Number(req.params.id)
across every handler. Better to push that work into the schema once.