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

# Policy impact handler

> decisions. Dry-run: bills nothing, logs nothing, persists nothing. **Required scope:** write

decisions. Dry-run: bills nothing, logs nothing, persists nothing.

**Required scope:** `write`

### Request body

`PolicyImpactRequest`

<ParamField body="add_rules" type="RecursiveChatRuleInput[]">
  Rules to ADD to the org policy for the candidate replay. Evaluated org-side (target-binding and declared-effect semantics identical to a stored org rule). Each rule must have exactly one conclusion.
</ParamField>

<ParamField body="limit" type="integer">
  Max logged decisions to replay, newest first (default 100, cap 500).
</ParamField>

<ParamField body="remove_rules" type="string[]">
  Names of existing org rules to REMOVE for the candidate replay.
</ParamField>

### Response

`PolicyImpactResponse`

<ResponseField name="candidate_outcomes" type="object" required>
  Verdict counts under the candidate policy, flipped or not.
</ResponseField>

<ResponseField name="evaluated" type="integer" required>
  Records replayed (had a request snapshot).
</ResponseField>

<ResponseField name="flips" type="PolicyImpactFlip[]" required>
  <Expandable title="PolicyImpactFlip">
    <ResponseField name="baseline" type="PolicyVerdict" required>
      <Expandable title="PolicyVerdict">
        <ResponseField name="cited_rules" type="string[]" required />

        <ResponseField name="outcome" type="string" required>
          `approved | denied | refused` — from the same outcome gate as live.
        </ResponseField>

        <ResponseField name="reason" type="string" required />
      </Expandable>
    </ResponseField>

    <ResponseField name="candidate" type="PolicyVerdict" required>
      <Expandable title="PolicyVerdict">
        <ResponseField name="cited_rules" type="string[]" required />

        <ResponseField name="outcome" type="string" required>
          `approved | denied | refused` — from the same outcome gate as live.
        </ResponseField>

        <ResponseField name="reason" type="string" required />
      </Expandable>
    </ResponseField>

    <ResponseField name="decision_id" type="string" required />

    <ResponseField name="original_outcome" type="string" required>
      The outcome the platform originally returned (includes neural context; shown for reference, not the comparison baseline).
    </ResponseField>

    <ResponseField name="query" type="string" required />
  </Expandable>
</ResponseField>

<ResponseField name="scope" type="string" required>
  What this replay does and does not evaluate.
</ResponseField>

<ResponseField name="skipped_no_snapshot" type="integer" required>
  Records skipped because they carried no request snapshot.
</ResponseField>

### Status codes

| Code  | Meaning                                                                                                 |
| ----- | ------------------------------------------------------------------------------------------------------- |
| `200` | Counterfactual replay report: outcome flips under the candidate policy                                  |
| `400` | A candidate rule cannot be represented as a stored org rule (multiple conclusions or a declared effect) |
| `401` | Unauthorized — missing or invalid credentials                                                           |
| `403` | Forbidden — the key/token lacks the required scope                                                      |
| `429` | Rate limited — see Retry-After / X-RateLimit-Reset                                                      |

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.nsr.stateset.com/v1/decisions/impact' \
    --header 'X-API-Key: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
    "add_rules": [
      {
        "category": "standard",
        "constraints": [],
        "description": "Two-person tent, green — replacement for damaged pole set.",
        "effect": {
          "0": "p",
          "1": "e",
          "2": "r",
          "3": "m",
          "4": "i",
          "5": "t"
        },
        "enabled": true,
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "if": [],
        "name": "Two-Person Tent",
        "priority": 1,
        "then": []
      }
    ],
    "limit": 20,
    "remove_rules": [
      "string"
    ]
  }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "candidate_outcomes": {},
    "evaluated": 1,
    "flips": [
      {
        "baseline": {
          "cited_rules": null,
          "outcome": null,
          "reason": null
        },
        "candidate": {
          "cited_rules": null,
          "outcome": null,
          "reason": null
        },
        "decision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "original_outcome": "string",
        "query": "string"
      }
    ],
    "scope": "string",
    "skipped_no_snapshot": 1
  }
  ```
</ResponseExample>
