# Validation

## Action Input Validation

You can validate input data in custom actions using Zod schemas. The input is validated before the action handler executes:

```typescript
// quickback/features/applications/actions.ts
import { defineActions } from '@quickback/compiler';
import { z } from 'zod';

export default defineActions(applications, {
  'advance-stage': {
    description: "Move application to the next pipeline stage",
    input: z.object({
      stage: z.enum(["screening", "interview", "offer", "hired"]),
      notes: z.string().min(1).max(500).optional(),
    }),
    access: { roles: ["owner", "hiring-manager"] },
    execute: async ({ db, record, ctx, input }) => {
      // input is validated against the Zod schema before execution
      return record;
    },
  },
});
```

If validation fails, the API returns a `400 Bad Request` with details about which fields failed.

See [Actions](/compiler/definitions/actions) for the full action definition reference.

> **Planned: Field-Level Validation**
>
> Field-level validation rules in `defineTable()` (e.g., `minLength`, `maxLength`, `enum`) are planned for a future release. Today, use Zod schemas in actions for input validation, and rely on your Drizzle schema constraints (`.notNull()`, column types) for database-level enforcement.

