> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Sample and validate requests

> Two commands generate requests that a rater accepts or refuses, and check one request against its input rules.

[Install Relativities](https://docs.canary.effectiveai.app/relativities/setup.md) before running the examples. The installation includes the `rslc` compiler.

`rslc inputs sample` reads the input rules of a rater and writes requests that pass them.
`rslc inputs validate` checks one request against the same rules.

The examples use the dwelling-fire rater from [Write your first rater](https://docs.canary.effectiveai.app/rsl/tutorial/first-rater.md).
Save its two files, or run `rslc examples get dwelling`.

> [accordion] dwelling/rater.rsl
>
> ```rsl dwelling/rater.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> spec {
>     rsl: "0.4.1",
>     carrier: "Example Mutual",
>     state: AZ,
>     product: "Dwelling Fire (tutorial)",
>     effective_date: 2026-01-01
> }
>
> Sources = {
>     manual: Source = {
>         artifact: artifact("00000000-0000-4000-8000-000000000000"),
>         kind: pdf
>     }
> }
>
> Types = {
>     Peril = {
>         fire,
>         wind,
>         theft
>     },
>     ProtectionClass = IntBands(1, 4, 7, 10..),
>     Money = Num {precision: 0.01}
> }
>
> Constants = {
>     expense_fee [cite: manual:p9] = 35
> }
>
> Tables = {
>     BaseRate [cite: manual:p3] :
>         table dims (protection: ProtectionClass) -> {
>             rate: Rate[Peril]
>         }
>         columns: {
>             rate[fire]: "fire",
>             rate[wind]: "wind",
>             rate[theft]: "theft"
>         }
> }
>
> Records = {
>     Policy = {
>         inputs {
>             dwelling: Dwelling,
>             items: List(Item)
>                 where len(self) in [0, 10] [code: "TOO-MANY-ITEMS", message: "A policy schedules at most ten items.", cite: manual:p6]
>         },
>         step premium {
>             base_rate[p: Peril]: Rate =
>                 lookup!(BaseRate, self.dwelling.protection_class).rate[p],
>             peril_premium[p: Peril]: Premium [cite: manual:p8] =
>                 round(self.dwelling.coverage_a / 1000 * self.base_rate[p], 2, half_up),
>             item_charge: Premium [cite: manual:p6] = sum(self.items as i, i.charge),
>             premium: Premium [cite: manual:p9] =
>                 round(sum(Peril as p, self.peril_premium[p]) + self.item_charge + expense_fee, 0, half_up)
>         }
>     },
>     Dwelling = {
>         inputs {
>             coverage_a: Money where self in [50000, 2000000],
>             protection_class: Num {precision: int}
>                 where self in [1, 10] [code: "PROTECTION-CLASS", message: "Protection class must be 1 to 10.", cite: manual:p4]
>         }
>     },
>     Item = {
>         inputs {
>             value: Money where self in [0.01, 50000]
>         },
>         step item {
>             charge: Premium [cite: manual:p6] = round(self.value * 0.015, 2, half_up)
>         }
>     }
> }
>
> RatingOutcomes = {
>     premium: Policy.premium
> }
> ```

> [accordion] dwelling/tables/BaseRate.csv
>
> ```csv dwelling/tables/BaseRate.csv theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> protection,fire,wind,theft
> 1,2.10,0.80,0.40
> 4,2.60,0.80,0.45
> 7,3.40,0.85,0.50
> 10,5.20,0.90,0.60
> ```

## Sample requests

Name the rater, the number of requests and a seed:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs sample dwelling/rater.rsl --n 3 --seed 7
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Generated 3 valid inputs from dwelling/rater.rsl
{"Policy": {"dwelling": {"coverage_a": 1668755.88, "protection_class": 5}, "items": [{"value": 43334}, {"value": 43296.19}]}}
{"Policy": {"dwelling": {"coverage_a": 1668755.88, "protection_class": 5}, "items": [{"value": 43334}, {"value": 21923.37}]}}
{"Policy": {"dwelling": {"coverage_a": 995442.35, "protection_class": 7}, "items": [{"value": 43334}, {"value": 16758.29}]}}
```

Each line after the first is one request, as JSON. Every value sits inside its declared range
and on its declared precision, so the rater accepts each request.

* `--n` sets the number of requests. The default is 20.
* `--seed` chooses the set. The default is 0.
* The requests of one set all differ.
* Each later request starts from an earlier one and redraws some values, so a value often repeats.

## Repeat a set

A seed fixes the set. The same command prints the same requests on every run and on every machine.

* A longer run starts with the same requests: `--n 4 --seed 7` prints these three, then a fourth.
* A different seed gives a different set.
* The set changes when the input rules of the rater change.
* The set also changes when a new version of `rslc` changes its sampler.

## Write the requests to a file

Add `--json-lines` and a file name:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs sample dwelling/rater.rsl --n 3 --seed 7 --json-lines requests.jsonl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Generated 3 valid inputs from dwelling/rater.rsl
...
```

The command prints the same lines and writes `requests.jsonl`, one record on each line.
A record holds the request under `input`. Its `generation` object holds the seed, the index of
the request and the version of the sampler.

Read the requests back and rate them:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
import json

from relativities import Rater

with open("requests.jsonl") as lines:
    requests = [json.loads(line)["input"] for line in lines]

rater = Rater.build("dwelling/rater.rsl")
print(rater.rate(requests).to_pandas()[["status", "premium"]])
#       status premium
# 0  succeeded    7759
# 1  succeeded    7439
# 2  succeeded    5665
```

## Sample refused requests

Add `--invalid` to get requests that the rater refuses:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs sample dwelling/rater.rsl --n 4 --seed 7 --invalid --json-lines refused.jsonl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Generated 4 invalid inputs from dwelling/rater.rsl
{"Policy": {"items": [{"value": 43334}, {"value": 43296.19}]}}
...
```

`--invalid` takes each sampled request and breaks one rule. The first request here lacks its
`dwelling` record. The second schedules eleven items, one more than the rater allows.

Each record in the file holds the broken request under `input` and the refusal under `refusal`:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
with open("refused.jsonl") as lines:
    for line in lines:
        refusal = json.loads(line)["refusal"]
        violation = refusal["violations"][0]
        print(refusal["error"], violation["code"], violation["path"])
# InvalidInputs INPUT-TYPE Policy.dwelling
# BusinessRejection TOO-MANY-ITEMS Policy.items
# InvalidInputs INPUT-TYPE Policy.dwelling
# BusinessRejection TOO-MANY-ITEMS Policy.items
```

The refusal is the one the rater returns for that request.
[Refusals](https://docs.canary.effectiveai.app/rsl/reference/refusals.md) describes each field and each code.

* `--invalid` breaks a rule of structure: a required record, the length of a list, a list key, or the kind of a record.
* The requests take turns over the rules that the rater declares. This rater declares two.
* `generation.mutation` names the change, such as `len.above_max@Policy.items`.
* To test a range rule, write the request and validate it, as the next section shows.

## Validate a request

Save a request as `request.json`:

```json request.json theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
{
  "Policy": {
    "dwelling": { "coverage_a": 250000, "protection_class": 5 },
    "items": [{ "value": 1200 }, { "value": 800 }]
  }
}
```

Name the rater, then the file:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs validate dwelling/rater.rsl request.json
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
PASS input for dwelling/rater.rsl
```

`PASS` means the request passes every input rule of the rater.

### Read a refused request

This request sends a Coverage A of 25,000 and protection class 12:

```json refused.json theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
{
  "Policy": {
    "dwelling": { "coverage_a": 25000, "protection_class": 12 },
    "items": []
  }
}
```

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs validate dwelling/rater.rsl refused.json
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
FAIL input for dwelling/rater.rsl
{'cite': None, 'code': 'INPUT-RANGE', 'constraint': 'coverage_a: where self in [50000, 2000000]', 'message': 'coverage_a is below declared minimum 50000', 'path': 'Policy.dwelling.coverage_a', 'value': 25000}
{'cite': 'manual:p4', 'code': 'PROTECTION-CLASS', 'constraint': 'protection_class: where self in [1, 10]', 'message': 'Protection class must be 1 to 10.', 'path': 'Policy.dwelling.protection_class', 'value': 12}
```

Each line after `FAIL` is one violation, with the six fields of a violation in a refusal.
The lines match the violations that rating the same request returns.

### Read the exit code

| Exit code | Meaning |
| - | - |
| 0 | The rater accepts the request |
| 1 | The rater refuses the request, or the file is missing or holds broken JSON |
| 2 | The command line has an error, such as a missing file name |

### Print JSON for a program

Add `--json` to print one JSON value:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc inputs validate dwelling/rater.rsl refused.json --json
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
{"candidate":"refused.json","command":"inputs.validate","ok":false,"source":"dwelling/rater.rsl","violations":[{"cite":null,"code":"INPUT-RANGE","constraint":"coverage_a: where self in [50000, 2000000]","message":"coverage_a is below declared minimum 50000","path":"Policy.dwelling.coverage_a","value":25000},{"cite":"manual:p4","code":"PROTECTION-CLASS","constraint":"protection_class: where self in [1, 10]","message":"Protection class must be 1 to 10.","path":"Policy.dwelling.protection_class","value":12}]}
```

`ok` is `true` for an accepted request, and `violations` is then an empty list.
The exit code stays the same. `rslc inputs sample` takes `--json` too, and prints the whole set as one value.

### Read the request from standard input

Write `-` in place of the file name:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
cat request.json | rslc inputs validate dwelling/rater.rsl -
```

The command prints the same lines as it prints for the file.

## Use the requests

* **Seed test cases.** Rate a seeded set, review the premiums, and keep each request with its premium. The seed rebuilds the same requests later. [Test a rater](https://docs.canary.effectiveai.app/rsl/how-to/test-a-rater.md) adds independent expected premiums.
* **Feed a what-if tool.** Load each `input` as a starting policy. Then change one value at a time and compare the premiums.
* **Check a request a host built.** Run `rslc inputs validate` on the request in the tests of the host. Exit code 0 shows that the rater accepts it.

## Related

* [Refusals](https://docs.canary.effectiveai.app/rsl/reference/refusals.md) lists the fields of a refusal, the codes and the order of the checks.
* [The command reference](https://docs.canary.effectiveai.app/rsl/reference/commands.md) lists every option of `rslc inputs`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.