---
sidebar_position: 8
title: Schemas
description: Define scalar and schema targets for typed JSON validation.
---
## Scalar Declarations
```hen
scalar HANDLE = string & len(3..24) & pattern(/^[a-z][a-z0-9_]*$/)
```
Scalar declarations can refine:
- primitive types
- built-in scalar targets
- named scalar declarations
Predicate forms are:
- `enum(value1, value2, ...)` where each value is a quoted string, integer, decimal number,
`true`, `false`, or `null`
- `format(NAME)` where `NAME` is one of `UUID`, `EMAIL`, `NUMBER`, `DATE`, `DATE_TIME`, `TIME`,
or `URI`
- `len(min..max)` for string length checks with inclusive integer bounds; either bound may be
omitted as in `len(3..)` or `len(..24)`, but not both
- `pattern(/regex/)` for string checks against a slash-delimited regular expression
- `range(min..max)` for numeric checks with inclusive integer or decimal bounds; either bound may
be omitted as in `range(0..)` or `range(..10.5)`, but not both
Scalar and schema references are resolved after the full preprocessed collection is loaded, so
forward references are allowed across the collection preamble and imported fragments.
## Schema Declarations
```hen
scalar Food = enum("pizza", "taco", "salad")
schema Address {
city: string
postalCode: string
}
schema User {
id: UUID
email: EMAIL
birthday?: DATE?
favoriteFood?: Food
address: Address
}
schema Users = User[]
```
- object fields are open by default in v1
- schema fields can reference named scalar declarations alongside built-in scalar targets and other schemas
- `field?: Type` marks an optional field
- `Type?` marks a nullable value
- `schema Name = Type[]` defines a root-array schema
Imported fragments can contribute reusable scalar and schema declarations before request parsing.
## Built-In Targets
Built-in scalar targets include:
- `UUID`
- `EMAIL`
- `NUMBER`
- `DATE`
- `DATE_TIME`
- `TIME`
- `URI`
Those names are reserved and cannot be redefined.
Built-in scalar targets are always available; you do not need to declare them locally.
## Assertion Use
```hen
^ & body.id === UUID
^ & body.total === NUMBER
^ & body === User
```
Use schema targets when you want typed validation instead of plain string comparison.