Documentation menu

Configuration

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.

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.

On this page

settlens check, settlens monitor and the 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.

The example file

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

JSONsettlens.config.example.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:

ShellRun a configuration
cp settlens.config.example.json settlens.config.json
settlens check --config settlens.config.json

Structure

TextOutline (generated from the schema)
{
  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
FieldType and rulesDescription
version1 (constant), requiredFormat version of the file.
failOnone of low, medium, high, critical, noneLowest severity of a failing check that makes settlens check exit 1; none never fails. Default high. --fail-on overrides it.
outputstring
non-empty
Directory for report files. Default reports. --out overrides it.
defaultsobject (see targetDefaults)Fields applied to every target before the target's own fields.
targetsarray of object (see target), 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
FieldType and rulesDescription
namestring
non-empty
Label used in the console and the report. Defaults to the URL hostname.
urlstring, required
starts with http:// or https://; at most 8192 characters
The paid resource to request. Credentials inside the URL are refused.
methodstring
letters only
HTTP method, upper-cased before use. Default GET.
headersobject (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.
bodystring
at most 1048576 characters
Request body, sent as is. Refused with GET and HEAD.
timeoutMsinteger
≥ 1; ≤ 300000
Per-request timeout in milliseconds. Default 8000. --timeout overrides it.
repeatinteger
≥ 1; ≤ 10
Identical passive requests used to compare payment terms. Default 2; 1 skips the stability check. --repeat overrides it.
expectedobject (see expected)Local policy and binding expectations for this target.
facilitatorstring or object (see facilitator)
starts with http:// or https://
Facilitator to cross-check with GET /supported: a base URL, or an object.
pricePolicyobject 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
FieldType and rulesDescription
resourceUrlstring
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.
schemesarray of string
1 to 32 items; no duplicates; each item: non-empty
Allowed schemes, compared case-insensitively.
networksarray 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.
payToarray 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.
assetsarray 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.
maxAmountstring
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. Why each constraint matters, and what a per-request policy cannot cover: AI agent spending policy for x402 payments.

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
FieldType and rulesDescription
namestringLabel for the facilitator. Defaults to its hostname.
urlstring, required
starts with http:// or https://; at most 8192 characters
Base URL. Settlens requests <url>/supported (and <url>/verify during an authorized active probe).
timeoutMsinteger
≥ 1
Per-request timeout in milliseconds. The loader accepts at most 300000.
headersobject (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.

JSONA header filled from the environment
"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:

TextValidation messages
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.

JSONsettlens.config.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, watch it with Monitor, or look up a finding in the check catalog.

Sources

  1. x402 Protocol Specification, version 2x402 Foundation · github.com
  2. CAIP-2: Blockchain ID SpecificationChain Agnostic Standards Alliance · github.com

Last updated