How to Implement API Request Validation

Validating incoming API requests before processing prevents a wide range of bugs, security issues, and confusing downstream errors. This guide covers implementing thorough, maintainable request validation.

Why Validate at the API Boundary

Every request entering your API is untrusted input, regardless of how "trusted" the client seems — validating at the boundary (before business logic runs) catches malformed data early, produces clearer error messages, and prevents invalid data from propagating deeper into your system.

Using a Schema Validation Library (Recommended Over Manual Checks)

npm install zod
const { z } = require('zod');

const CreateProductSchema = z.object({
  name: z.string().min(1).max(200),
  price: z.number().positive(),
  category: z.enum(['electronics', 'clothing', 'food']),
});

app.post('/api/products', (req, res) => {
  const result = CreateProductSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({ errors: result.error.issues });
  }
  const validatedData = result.data;
});

A schema library provides declarative, maintainable validation, automatically generating clear error messages — far more sustainable than scattered manual if checks throughout your route handlers.

Validating Query Parameters and Path Parameters Too

const ProductQuerySchema = z.object({
  limit: z.coerce.number().int().min(1).max(100).default(20),
  category: z.string().optional(),
});

Don't validate only request bodies — query parameters, path parameters, and headers are equally untrusted input warranting the same validation discipline.

Returning Clear, Actionable Error Messages

{
  "errors": [
    { "field": "price", "message": "Price must be a positive number" }
  ]
}

Vague errors ("Invalid input") frustrate API consumers trying to debug their integration — specific, field-level error messages significantly improve the developer experience for anyone integrating with your API.

Sanitizing, Not Just Validating

Beyond checking format/type validity, consider whether input needs sanitization (trimming whitespace, normalizing case, stripping potentially dangerous characters for specific contexts) before use — validation confirms structure; sanitization prepares the actual value for safe use.

Validating Nested and Complex Structures

const OrderSchema = z.object({
  items: z.array(z.object({
    productId: z.string(),
    quantity: z.number().int().positive(),
  })).min(1),
});

Schema libraries handle nested object/array validation cleanly — important for genuinely complex API payloads where manual validation logic becomes unwieldy.

Consistent Validation Middleware Pattern

function validate(schema) {
  return (req, res, next) => {
    const result = schema.safeParse(req.body);
    if (!result.success) return res.status(400).json({ errors: result.error.issues });
    req.validatedData = result.data;
    next();
  };
}

app.post('/api/products', validate(CreateProductSchema), handler);

A reusable middleware pattern keeps validation logic consistent and DRY across your routes, rather than repeating validation boilerplate in every handler.

Relationship to General OWASP Input Validation Guidance

See Understanding and Mitigating the OWASP Top 10 Vulnerabilities — thorough input validation is a foundational defense against injection and several other vulnerability categories; it's a security practice, not just a data-quality one.

Common Errors

Validation passes but a downstream error still occurs with "invalid" data — ensure your schema genuinely captures all the constraints your business logic actually requires, not just basic type checking; schema validation should reflect real business rules, not just superficial structure.

Continue Reading

Browse more articles in Object Storage, Messaging & APIs.

  • api request validation, zod schema validation, input validation api security, api validation middleware
  • 0 Kunder som kunne bruge dette svar
Hjalp dette svar dig?

Relaterede artikler

How to Set Up Self-Hosted S3-Compatible Object Storage with MinIO

MinIO is a high-performance, self-hosted object storage server compatible with the S3 API —...

How to Use Object Storage for Application File Uploads

Storing user-uploaded files directly on your application server's disk creates scaling and...

How to Install and Configure RabbitMQ on a VPS

RabbitMQ is a widely-used, robust message broker — enabling applications to communicate...

How to Install and Configure Redis as a Message Queue

Redis, primarily known as a cache, also works well as a lightweight message queue for simpler use...

How to Build and Secure a REST API on a VPS

This guide covers the essential security and architecture practices for deploying a REST API on...