> ## Documentation Index
> Fetch the complete documentation index at: https://developer.uphold.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic forms JSON Schema reference

> Reference for the JSON Schema that defines dynamic form data structure, types, and validation rules. Covers properties, required fields, and constraints.

The JSON Schema defines the data structure, types, and validation rules for dynamic forms. It follows the [JSON Schema](https://json-schema.org/) specification.

## Structure

A schema defines an `object` with `properties`. Each property specifies its type and validation constraints:

```json theme={null}
{
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "age": {
      "type": "number"
    }
  },
  "required": ["firstName"]
}
```

The `required` array lists properties that must be provided when submitting the form.

## Steps

Root-level properties in the schema represent **steps** — logical groupings of related questions. Each step is an object containing the fields the user needs to complete.

A form with one step:

```json theme={null}
{
  "type": "object",
  "properties": {
    "personalInfo": {
      "type": "object",
      "properties": {
        "firstName": { "type": "string" },
        "lastName": { "type": "string" }
      }
    }
  }
}
```

A form with two steps:

```json theme={null}
{
  "type": "object",
  "properties": {
    "personalInfo": {
      "type": "object",
      "properties": {
        "firstName": { "type": "string" },
        "lastName": { "type": "string" }
      }
    },
    "contactInfo": {
      "type": "object",
      "properties": {
        "email": { "type": "string" },
        "phone": { "type": "string" }
      }
    }
  }
}
```

### Progressive disclosure

Steps enable **progressive disclosure** — as the user completes one step and submits their answers, the API may return an updated schema with new steps revealed. This means the schema grows dynamically based on previous answers, allowing you to guide users through a multi-step flow without showing all questions upfront.

## Types

### String

Text values, typically rendered as text inputs.

```json theme={null}
{
  "type": "string"
}
```

### Number

Numeric values, typically rendered as number inputs.

```json theme={null}
{
  "type": "number"
}
```

### Boolean

True/false values, typically rendered as checkboxes or toggles.

```json theme={null}
{
  "type": "boolean"
}
```

### Array

Lists of items, typically rendered as multi-selects or repeatable sections.

```json theme={null}
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "country": { "type": "string" },
      "taxId": { "type": "string" }
    }
  },
  "minItems": 1,
  "maxItems": 5
}
```

### Object

Nested structures with their own properties.

```json theme={null}
{
  "type": "object",
  "properties": {
    "street": { "type": "string" },
    "city": { "type": "string" },
    "postalCode": { "type": "string" }
  }
}
```

## Formats

The `format` keyword provides semantic meaning to string values.

### Date

Date values, typically rendered as date pickers.

```json theme={null}
{
  "type": "string",
  "format": "date"
}
```

<Note>
  Custom display formats (e.g., `postal-code`) are defined in the UI Schema via [`options.format`](/developer-guides/resources/dynamic-forms/ui-schema#format), not in the JSON Schema.
</Note>

## Validation keywords

### String validation

| Keyword     | Description                             |
| ----------- | --------------------------------------- |
| `minLength` | Minimum number of characters            |
| `maxLength` | Maximum number of characters            |
| `pattern`   | Regular expression the value must match |

```json theme={null}
{
  "type": "string",
  "pattern": "^[A-Z]{2}[0-9]{9}$",
  "minLength": 11,
  "maxLength": 11
}
```

### Array validation

| Keyword       | Description                                       |
| ------------- | ------------------------------------------------- |
| `minItems`    | Minimum number of items                           |
| `maxItems`    | Maximum number of items                           |
| `uniqueItems` | When `true`, all items must be unique             |
| `contains`    | At least one item must match the specified schema |

```json theme={null}
{
  "type": "array",
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}
```

### Enumeration and constants

#### enum

Restricts a property to a predefined list of allowed values.

```json theme={null}
{
  "type": "string",
  "enum": ["employed", "self-employed", "retired", "student", "unemployed"]
}
```

#### const

Restricts a property to a single fixed value.

```json theme={null}
{
  "type": "string",
  "const": "agreed"
}
```

#### oneOf

Allows a value to match one of several schemas. Often used for conditional validation based on a previous answer.

```json theme={null}
{
  "oneOf": [
    {
      "properties": {
        "employmentStatus": { "const": "employed" },
        "employerName": { "type": "string" }
      },
      "required": ["employerName"]
    },
    {
      "properties": {
        "employmentStatus": { "const": "self-employed" },
        "businessName": { "type": "string" }
      },
      "required": ["businessName"]
    },
    {
      "properties": {
        "employmentStatus": { "enum": ["retired", "student", "unemployed"] }
      }
    }
  ]
}
```

In this example, users who select "employed" must provide an employer name, those who select "self-employed" must provide a business name, and other statuses require no additional information.

## Next steps

<CardGroup cols={2}>
  <Card title="UI Schema" icon="table-layout" href="./ui-schema">
    Learn how to render forms with layouts, controls, and rules.
  </Card>

  <Card title="Rendering" icon="code" href="./rendering">
    Implementation guidance and best practices.
  </Card>
</CardGroup>
