Skip to main content

Flexible API Validation

This recipe shows how to configure the generator to allow extra fields in API requests while maintaining strict validation for internal schemas.

Problem​

By default, all generated Zod schemas include .strict(), which rejects any extra properties. This can be problematic when:

  • Integrating with external APIs that send additional fields
  • Building APIs that should ignore unknown fields
  • Developing frontend applications that might send extra data

Solution​

Use strict mode configuration to disable .strict() for operation schemas while keeping it for internal object schemas:

zod-generator.config.json
{
"strictMode": {
"enabled": true,
"operations": false,
"objects": true,
"variants": true
}
}
  • enabled: true keeps schemas strict by default.
  • operations: false allows extra fields in the CRUD operation schemas.
  • objects: true keeps the objects/ input schemas strict for internal validation.
  • variants: true keeps the pure/input/result variant schemas strict.

Result​

Before (Default Strict)​

// API operation schema - rejects extra fields
export const UserCreateOneSchema = z.object({
data: z.union([UserCreateInputObjectSchema, UserUncheckedCreateInputObjectSchema])
}).strict(); // ← Rejects extra fields

// Internal object schema - rejects extra fields
export const UserCreateInputObjectSchema = z.object({
name: z.string(),
email: z.string()
}).strict(); // ← Rejects extra fields

After (Flexible Operations)​

// API operation schema - allows extra fields
export const UserCreateOneSchema = z.object({
data: z.union([UserCreateInputObjectSchema, UserUncheckedCreateInputObjectSchema])
}); // ← No .strict() - allows extra fields

// Internal object schema - still strict
export const UserCreateInputObjectSchema = z.object({
name: z.string(),
email: z.string()
}).strict(); // ← Still strict for internal validation

Usage Example​

Client Request (Now Works)​

operations: false relaxes the outer operation schema, so the extra fields belong at the top level — the contents of data are still validated by the strict object schema:

// This request now succeeds even with extra fields
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({
data: {
name: 'John Doe',
email: 'john@example.com'
},
// Extra fields from frontend - ignored by the non-strict operation schema
clientVersion: '1.2.3',
trackingId: 'abc123',
timestamp: Date.now()
})
});
caution

Extra keys placed inside data are still rejected while strictMode.objects is true. Set "objects": false as well if your clients send unknown fields inside data.

Server Validation​

import { UserCreateOneSchema } from './generated/schemas';

export async function createUser(req: Request) {
// Parse and validate - extra fields are ignored
const parsed = UserCreateOneSchema.parse(req.body);

// Only the defined fields are present
console.log(parsed);
// { data: { name: 'John Doe', email: 'john@example.com' } }

// Safe to pass to Prisma
const user = await prisma.user.create(parsed);
return user;
}

Advanced Configuration​

Per-Model Flexibility​

Allow extra fields only for specific models — strictMode is strict by default, and only User operations and every PublicProfile schema opt out:

zod-generator.config.json
{
"strictMode": {
"enabled": true,
"operations": true
},
"models": {
"User": {
"strictMode": {
"operations": false
}
},
"PublicProfile": {
"strictMode": {
"enabled": false
}
}
}
}

Operation-Specific Control​

Narrow strict mode down to individual operations:

zod-generator.config.json
{
"models": {
"User": {
"strictMode": {
"operations": ["create", "update"],
"exclude": ["findMany"]
}
}
}
}
  • operations as an array is an allow-list for strict mode: only create and update get .strict(). Every other User operation drops it and therefore accepts extra fields.
  • exclude removes operations from strict mode and wins over operations, so findMany accepts extra fields.

Both short names (create, update) and full operation names (createOne, updateOne) are accepted.

Environment-Based Configuration​

Development (Permissive)​

zod-generator.config.dev.json
{
"strictMode": {
"enabled": false,
"variants": true
}
}

enabled: false relaxes operation and object schemas, while variants: true keeps the pure/input/result variant schemas strict for type safety. Enum schemas are plain z.enum([...]) and are not affected by strictMode at all.

Production (Strict)​

zod-generator.config.prod.json
{
"strictMode": {
"enabled": true,
"operations": false
}
}

Strict everywhere except operations, for API flexibility.

Selecting a config per environment​

The Prisma schema language has no conditionals, so the config attribute cannot branch on an environment variable. Instead, omit config and let the generator auto-discover zod-generator.config.json next to your schema:

schema.prisma
generator zod {
provider = "prisma-zod-generator"
output = "./generated/schemas"
}

Then put the right file in place before generating:

# development
cp zod-generator.config.dev.json zod-generator.config.json
npx prisma generate

# production
cp zod-generator.config.prod.json zod-generator.config.json
npx prisma generate

Best Practices​

  1. Start Conservative: Begin with strict validation and selectively allow flexibility
  2. Validate Boundaries: Keep internal schemas strict while allowing flexibility at API boundaries
  3. Test Thoroughly: Ensure your application handles extra fields gracefully
  4. Document Decisions: Comment why certain models/operations allow extra fields
  5. Monitor Production: Log when extra fields are received to understand usage patterns
  • Gradual Migration: Gradually moving from strict to flexible validation
  • Input Validation: Different validation strategies for different schema types
  • API Integration: Working with external APIs that send extra data

Common Issues​

Still Getting Validation Errors​

If you're still getting strict validation errors:

  1. Check that you're validating with an operation schema (e.g. UserCreateOneSchema), not an object schema (e.g. UserCreateInputObjectSchema) — strictMode.operations only affects the former
  2. Verify your configuration is properly loaded
  3. Ensure you've regenerated schemas after configuration changes

Performance Considerations​

Allowing extra fields has minimal performance impact, but consider:

  • Extra fields are parsed but ignored (not passed to Prisma)
  • Large payloads with many extra fields use more memory during parsing
  • Consider request size limits for APIs that accept extra fields