Skip to main content
A Schema validation library is available globally in every backend script. It provides a Joi-like fluent API to validate, coerce, and sanitize incoming data — especially request.body from POST requests, but usable with any object. The library is pure JavaScript and runs directly in the sandbox. No imports needed — Schema is a global.

Quick start

How it works

  1. Define a schema using Schema.string(), Schema.number(), etc.
  2. Chain validators: .required(), .min(5), .email(), etc.
  3. Call schema.validate(data) — returns { valid, value, errors }
  4. If valid is true, value contains a deep-cloned, type-coerced copy of the input
  5. If valid is false, errors is an array of human-readable error messages
validate() returns a deep clone of the input. The original request.body is never mutated. Unknown keys in objects are silently dropped — only keys defined in the schema are kept.

Types

Schema.string()

Validates that the value is a string.

Schema.number()

Validates that the value is a number. Strings like "42" are auto-coerced.

Schema.boolean()

Validates that the value is a boolean. Strings "true", "1", "false", "0" are auto-coerced.

Schema.array()

Validates arrays. Use .items() to validate each element.

Schema.object()

Validates objects. Pass a key map to define the shape.
Unknown keys are automatically stripped — only keys in the schema are kept in result.value. This prevents users from injecting unexpected fields.

Dynamic keys

For objects where keys are not known ahead of time, use .pattern_values():
This validates that every value in the object (regardless of key name) matches the rule.

Schema.any()

Accepts any type. Useful with .required() or .valid().

Modifiers

Type coercion

The validator automatically coerces compatible types: Non-coercible values fail validation (e.g. "hello" for Schema.number()).

Custom validators

Use .custom() for logic that built-in methods don’t cover:
The function receives (value, label) and should return an error string if validation fails, or nothing/undefined if it passes.

Full POST example

A page at /api/submit-checkin that validates and stores data:
Frontend:

Nested object example

Always validate before storing. Even though the Schema library strips unknown keys and enforces types, it’s a good practice to apply .max() constraints on strings and arrays to prevent large payloads from consuming CRM storage.