hen 0.19.0

Run protocol-aware API request collections from the command line or through MCP.
Documentation
---
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.