---
title: "Configuration file reference | Settlens"
description: "Settlens configuration reference: targets, defaults, policy, facilitator and headers, generated from the JSON Schema, with examples and validation rules."
url: https://settlens.com/docs/configuration
last_updated: 2026-10-13
---

# Configuration

> **In short:** A Settlens configuration is a JSON file (version 1) listing 1 to 100 targets, with optional shared defaults, a failOn threshold and an output directory. Each target can set a policy (expected), a facilitator and custom headers. settlens check, settlens monitor and the GitHub Action read it.

The JSON file that settlens check, settlens monitor and the GitHub Action read: every field, its rules and how it combines with command-line options.

`settlens check`, `settlens monitor` and the [GitHub Action](https://settlens.com/docs/github-action) read their targets from a JSON file. The tables on this page are generated from the JSON Schema shipped in the repository (`schemas/settlens-config.schema.json`), so they match the version of Settlens that built this site. The loader in `src/config.js` applies the same rules, except two that only a schema-aware editor reports (unique entries in each list, and the CAIP-2 format of `expected.networks`), plus a few the schema cannot express, listed under [Validation](https://settlens.com/docs/configuration#validation).

## The example file

The repository ships `settlens.config.example.json`, which targets the local demo server:

**settlens.config.example.json**

```json
{
  "version": 1,
  "failOn": "high",
  "output": "reports",
  "defaults": {
    "method": "GET",
    "timeoutMs": 8000,
    "repeat": 2
  },
  "targets": [
    {
      "name": "local-secure-demo",
      "url": "http://127.0.0.1:4402/secure",
      "facilitator": "http://127.0.0.1:4402/facilitator",
      "expected": {
        "resourceUrl": "http://127.0.0.1:4402/secure",
        "schemes": [
          "exact"
        ],
        "networks": [
          "eip155:84532"
        ],
        "payTo": [
          "0x209693Bc6afc0C5328bA36FaF03C514EF312287C"
        ],
        "assets": [
          "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
        ],
        "maxAmount": "10000"
      }
    }
  ]
}
```

1. `version` is required and must be `1`.
2. `failOn` and `output` set the CI threshold and the report directory for the whole file.
3. `defaults` holds values shared by every target, here the method, the timeout and the number of samples.
4. Each entry of `targets` names one paid resource. This one also cross-checks the demo facilitator and pins a policy: scheme, network, recipient, asset, ceiling and the exact resource URL.

Copy it, point it at your own endpoints, then run it. Start the demo server first (`npm run demo:server`) to try the file as is:

**Run a configuration**

```shell
cp settlens.config.example.json settlens.config.json
settlens check --config settlens.config.json
```

## Structure

**Outline (generated from the schema)**

```text
{
  version, failOn, output
  defaults: { method, headers, body, timeoutMs, repeat, expected, facilitator, pricePolicy }
  targets: [
    { name, url, method, headers, body, timeoutMs, repeat, expected, facilitator, pricePolicy }
  ]
}

expected:    { resourceUrl, schemes, networks, payTo, assets, maxAmount }
facilitator: "<base-url>" or { name, url, timeoutMs, headers }
headers:     { "Header-Name": "value", … }
```

## Top-level fields

_Top-level fields_

| Field | Type and rules | Description |
| --- | --- | --- |
| version | 1 (constant), required | Format version of the file. |
| failOn | one of low, medium, high, critical, none | Lowest severity of a failing check that makes settlens check exit 1; none never fails. Default high. --fail-on overrides it. |
| output | string; non-empty | Directory for report files. Default reports. --out overrides it. |
| defaults | object (see [targetDefaults](https://settlens.com/docs/configuration#defaults)) | Fields applied to every target before the target's own fields. |
| targets | array of object (see [target](https://settlens.com/docs/configuration#target-fields)), required; 1 to 100 items | The paid resources to assess. |

Any other top-level field is rejected, including `$schema`: point your editor at the schema file through its own settings rather than inside the config.

## Target fields

_Fields of each entry in targets_

| Field | Type and rules | Description |
| --- | --- | --- |
| name | string; non-empty | Label used in the console and the report. Defaults to the URL hostname. |
| url | string, required; starts with http:// or https://; at most 8192 characters | The paid resource to request. Credentials inside the URL are refused. |
| method | string; letters only | HTTP method, upper-cased before use. Default GET. |
| headers | object (name → string); at most 64 entries; names are HTTP header tokens; PAYMENT-SIGNATURE is rejected; values: no line breaks, at most 65536 characters | Extra request headers, for example authentication for a staging gateway. Values never reach a report; the destination host must be allowlisted. |
| body | string; at most 1048576 characters | Request body, sent as is. Refused with GET and HEAD. |
| timeoutMs | integer; ≥ 1; ≤ 300000 | Per-request timeout in milliseconds. Default 8000. --timeout overrides it. |
| repeat | integer; ≥ 1; ≤ 10 | Identical passive requests used to compare payment terms. Default 2; 1 skips the stability check. --repeat overrides it. |
| expected | object (see [expected](https://settlens.com/docs/configuration#expected)) | Local policy and binding expectations for this target. |
| facilitator | string or object (see [facilitator](https://settlens.com/docs/configuration#facilitator)); starts with http:// or https:// | Facilitator to cross-check with GET /supported: a base URL, or an object. |
| pricePolicy | object or object |  |

## Defaults

`defaults` accepts the target fields except `name` and `url`: `method`, `headers`, `body`, `timeoutMs`, `repeat`, `expected`, `facilitator`, `pricePolicy`. Each target is built as `{ ...defaults, ...target }`, a shallow merge: a target that sets `headers` or `expected` replaces the whole default object instead of adding to it.

## Expected: policy and binding

_Fields of expected_

| Field | Type and rules | Description |
| --- | --- | --- |
| resourceUrl | string; starts with http:// or https://; at most 8192 characters | URL that resource.url must equal. Defaults to the target url; set it when the canonical resource URL differs from the URL requested. |
| schemes | array of string; 1 to 32 items; no duplicates; each item: non-empty | Allowed schemes, compared case-insensitively. |
| networks | array of string; 1 to 32 items; no duplicates; each item: CAIP-2 identifier (namespace:reference) | Allowed CAIP-2 networks, compared case-insensitively, for example eip155:8453. |
| payTo | array of string; 1 to 32 items; no duplicates; each item: non-empty | Allowed recipients. EVM hex addresses compare case-insensitively; other formats, such as Solana base58, compare exactly. |
| assets | array of string; 1 to 32 items; no duplicates; each item: non-empty | Allowed assets (token contract addresses or mints). EVM hex addresses compare case-insensitively; other formats compare exactly. |
| maxAmount | string; digits only (integer string) | Ceiling for every advertised amount, in the asset's atomic units. |

In a scan, the server must only _advertise_ allowed terms: each policy check fails as soon as one advertised option falls outside the policy, even if another option would be acceptable. Fields you leave out are not checked. The resulting checks are listed under [policy checks](https://settlens.com/docs/checks#policy-checks). Why each constraint matters, and what a per-request policy cannot cover: [AI agent spending policy for x402 payments](https://settlens.com/learn/agent-spending-policy).

> **Pair maxAmount with assets**
>
> `maxAmount` is a number of atomic units, and tokens use different decimals: 10000 is 0.01 of a 6-decimal token and far less of an 18-decimal one. Set `assets` together with `maxAmount` so the ceiling refers to a known token.

## Facilitator

`facilitator` is either a base URL string (`"https://facilitator.example"`) or an object. Settlens appends `/supported` unless the URL already ends with it, adds the facilitator checks, and checks that every scheme and network the resource advertises is supported.

_Fields of the facilitator object_

| Field | Type and rules | Description |
| --- | --- | --- |
| name | string | Label for the facilitator. Defaults to its hostname. |
| url | string, required; starts with http:// or https://; at most 8192 characters | Base URL. Settlens requests \<url>/supported (and \<url>/verify during an authorized active probe). |
| timeoutMs | integer; ≥ 1 | Per-request timeout in milliseconds. The loader accepts at most 300000. |
| headers | object (name → string); at most 64 entries; names are HTTP header tokens; PAYMENT-SIGNATURE is rejected; values: no line breaks, at most 65536 characters | Extra request headers for the facilitator, under the same rules as target headers. |

## Headers and secrets

- At most 64 headers per target or facilitator, each value a string of at most 65536 characters without line breaks. Names must be valid HTTP header tokens.
- `PAYMENT-SIGNATURE` is refused in any letter case: Settlens never forwards a real payment authorization.
- Every host that receives a custom header must be allowlisted outside the file, with `SETTLENS_ALLOWED_HOSTS` (comma-separated exact hostnames) or the Action's `allowed-hosts` input. Otherwise the run stops with `Custom headers require an explicit allowed host.` This keeps an edited config from sending CI secrets to a new host.
- Reports record header names only, never values.

## Environment variables

Any string in the file can reference an environment variable as `${NAME}`, where `NAME` uses uppercase letters, digits and underscores. Values are expanded when the file is loaded; a missing variable stops the run with `Environment variable NAME is required by the config.` Use it for tokens in headers. Do not put secrets in URLs: target URLs appear in reports, with only common secret query parameters redacted.

**A header filled from the environment**

```json
"headers": {
  "Authorization": "Bearer ${ASSESSMENT_TOKEN}"
}
```

## Precedence

- Report directory: `--out`, then `output`, then `reports`.
- Failure threshold: `--fail-on`, then `failOn`, then `high`.
- Timeout: `--timeout`, then the target's `timeoutMs` (after defaults), then 8000 ms. Facilitator requests use `--timeout`, then the facilitator object's own `timeoutMs`, then 8000 ms; the target's `timeoutMs` does not apply to them.
- Samples: `--repeat`, then the target's `repeat`, then 2.
- Active probe: only from the command line (`--active --authorized --authorization-ref`), never from the file.

## Validation

The file is checked before any request is sent. A problem exits with code 2 and one message. Some real messages:

**Validation messages**

```text
Settlens error: Config contains unsupported field(s): $schema.
Settlens error: Config version must equal 1.
Settlens error: Target 0 must not provide a body for GET.
Settlens error: Target 0 expected.maxAmount must be an integer string.
Settlens error: Target 0 has an invalid URL: Target 0 URL credentials are forbidden; use reviewed headers.
Settlens error: Target 0 must not provide PAYMENT-SIGNATURE. Settlens never sends real payment authorizations.
Settlens error: Environment variable ASSESSMENT_TOKEN is required by the config.
```

The loader also requires 1 to 100 targets, rejects unknown fields at every level, accepts only `http` and `https` URLs, and requires `maxAmount` to be a string of digits so large atomic amounts keep their precision.

## A fuller example

Two targets that share a policy through `defaults` (USDC on Base mainnet, at most 0.01 USDC), one of them behind an authenticated staging gateway. Run it with `SETTLENS_ALLOWED_HOSTS=staging.merchant.example` and `ASSESSMENT_TOKEN` set.

**settlens.config.json**

```json
{
  "version": 1,
  "failOn": "high",
  "output": "reports",
  "defaults": {
    "timeoutMs": 8000,
    "repeat": 2,
    "expected": {
      "schemes": [
        "exact"
      ],
      "networks": [
        "eip155:8453"
      ],
      "payTo": [
        "0x209693Bc6afc0C5328bA36FaF03C514EF312287C"
      ],
      "assets": [
        "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
      ],
      "maxAmount": "10000"
    }
  },
  "targets": [
    {
      "name": "weather-api",
      "url": "https://api.merchant.example/v1/weather?city=paris",
      "facilitator": "https://facilitator.example"
    },
    {
      "name": "staging-report",
      "url": "https://staging.merchant.example/v1/report",
      "method": "POST",
      "body": "{\"period\":\"2026-Q3\"}",
      "headers": {
        "Authorization": "Bearer ${ASSESSMENT_TOKEN}"
      },
      "facilitator": {
        "name": "staging-facilitator",
        "url": "https://facilitator.example",
        "timeoutMs": 5000
      }
    }
  ]
}
```

The second target sets its own `headers` and `facilitator`; it still inherits `expected`, `timeoutMs` and `repeat` from `defaults`.

Next: run the file in CI with the [GitHub Action](https://settlens.com/docs/github-action), watch it with [Monitor](https://settlens.com/docs/monitor), or look up a finding in the [check catalog](https://settlens.com/docs/checks).

## Sources

1. [x402 Protocol Specification, version 2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md) — x402 Foundation
2. [CAIP-2: Blockchain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) — Chain Agnostic Standards Alliance
