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

# Multi-set rule configuration example

> Placement, stop behavior, and event-start snapshots across three rule sets

This example publishes three rule sets: base earning, a promotional fallback pair, and purchase tracking. Every set with a matching `ACTIVE` rule runs.

## Final run order

| Set               | Rules                                             | Behavior                                                      |
| ----------------- | ------------------------------------------------- | ------------------------------------------------------------- |
| Base earning      | Base purchase points                              | Credits the purchase amount.                                  |
| Summer promotions | Premium bonus, then standard bonus                | A premium match stops only the standard fallback in this set. |
| Purchase tracking | Increment purchase count, then tag tenth purchase | Keeps state changes separate from earning logic.              |

A premium purchase receives base earning plus the premium promotional credit. The premium rule has a per-rule budget. Budget exhaustion skips that rule and lets evaluation continue to the fallback and later sets.

## Use semantic positions

Insert a new set before an existing one without choosing a numeric order:

```json theme={null}
{
  "key": "summer-promotions",
  "name": "Summer promotions",
  "position": {
    "placement": "before",
    "reference_id": "71000000-0000-4000-8000-000000000012"
  }
}
```

Move a rule after a sibling with the current revision guard:

```json theme={null}
{
  "rule_set_id": "71000000-0000-4000-8000-000000000011",
  "position": {
    "placement": "after",
    "reference_id": "71000000-0000-4000-8000-000000000021"
  },
  "expected_rule_configuration_version": 7
}
```

For an atomic proposal, the `rule_sets` array and each nested `rules` array carry the final order. Do not send temporary numeric order values.

## Keep mutually exclusive rates inside one set

```json theme={null}
{
  "client_ref": "summer_promotions",
  "key": "summer-promotions",
  "name": "Summer promotions",
  "rules": [
    {
      "client_ref": "premium_bonus",
      "name": "Premium member bonus",
      "condition": "event.type == 'purchase' && event.segment == 'premium'",
      "actions": [
        {
          "type": "CREDIT",
          "asset_id": "71000000-0000-4000-8000-000000000020",
          "amount": "${{ event.amount }}"
        }
      ],
      "budgets": [{"asset_id": "71000000-0000-4000-8000-000000000020", "limit": "10000"}],
      "status": "ACTIVE",
      "stop_after_match": true
    },
    {
      "client_ref": "standard_bonus",
      "name": "Standard summer bonus",
      "condition": "event.type == 'purchase'",
      "actions": [
        {
          "type": "CREDIT",
          "asset_id": "71000000-0000-4000-8000-000000000020",
          "amount": "${{ event.amount * 0.25 }}"
        }
      ],
      "budgets": [],
      "status": "ACTIVE",
      "stop_after_match": false
    }
  ]
}
```

`premium_bonus` skips only `standard_bonus` after a successful match. Base earning and tracking still run in their sets.

## Test the snapshot dependency

The tracking set increments `purchase_count`, then checks whether the participant reached ten purchases:

```json theme={null}
[
  {
    "client_ref": "increment_purchase_count",
    "name": "Increment purchase count",
    "condition": "event.type == 'purchase'",
    "actions": [{"type": "COUNTER", "key": "purchase_count", "value": "1"}],
    "budgets": [],
    "status": "ACTIVE",
    "stop_after_match": false
  },
  {
    "client_ref": "tag_tenth_purchase",
    "name": "Tag tenth purchase",
    "condition": "event.type == 'purchase' && participant.counter.purchase_count >= 9",
    "actions": [{"type": "TAG", "tag": "TEN_PURCHASES"}],
    "budgets": [],
    "status": "ACTIVE",
    "stop_after_match": false
  }
]
```

Both conditions read the event-start count. When the count starts at `8`, the event ends at `9` and the tag does not apply. When it starts at `9`, the tag applies and the event ends at `10`. Moving the second rule to a later set would not make it see the same-event increment.

## Ground and diagnose a typo

Before publish, compare the draft's `event.type`, `event.amount`, and `event.segment` references with observed shapes. If the draft says `event.segmnet`, clause diagnostics show a missing field during simulation, while the observed-shape inventory shows `segment` in real traffic.

Fix the field name before publishing. Follow [Managing rule configuration](/guides/managing-rule-configuration) to analyze, test, preview, apply, and verify the draft.

## Suspend, reactivate, and roll back

A suspended rule stays in its set and keeps its position. Keep its existing `id` in a complete draft and switch `status` between `SUSPENDED` and `ACTIVE`. Omitting the rule archives it.

Rollback creates a new forward revision. Preview the historical target, review the inverse diff and warnings, then apply it through the standard configuration apply endpoint. Past revisions stay unchanged.
