---
title: "Create a rule set"
method: POST
path: "/v1/programs/{program_id}/rule-sets"
tags: ["Rule Sets"]
---

# Create a rule set

`POST /v1/programs/{program_id}/rule-sets`

## Request

- Base URL: `https://api.scrip.dev`
- URL: `https://api.scrip.dev/v1/programs/{program_id}/rule-sets`
- Auth: HTTP bearer

Create a named rule set. Omit position to append, or use first/last/before/after placement. Positions are renumbered to 1..N with no gaps. All sets containing applicable ACTIVE rules participate; position controls execution priority only. The response includes the resulting rule_configuration_version.

## Path parameters

- `program_id` string, uuid, required

## Headers

- `Idempotency-Key` string

## Request body

- CreateRuleSetRequest: Creates a rule set in a program.
  - `key` string, required: Immutable program-scoped key. Must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, or underscores.
  - `name` string, required: Operator-facing display name.
  - `position` SemanticPositionRequest: Where to place a resource: first, last, or before or after another resource.
    - `placement` 'before' | 'after', required: Placement within the destination collection.
    - `reference_id` string, uuid, required: Stable sibling ID. Required for before/after and omitted for first/last.

## Response `201`

Rule set created

- RuleSetResponse: A rule set: an ordered group of rules in a program.
  - `created_at` string, date-time: When this rule set was created.
  - `id` string, uuid: The id of the rule set. Use it in `rule_set_id` fields and paths.
  - `key` string: Immutable program-scoped key.
  - `name` string: Operator-facing display name.
  - `order` integer: Execution position among participating sets; lower executes first. This does not control participation, stacking, replacement, or suppression.
  - `program_id` string, uuid: Program that owns this rule set.
  - `rule_configuration_version` integer: Resulting program rule-configuration revision. Present on mutation responses.
  - `updated_at` string, date-time: When this rule set was last modified.

## Other responses

- `400`: Malformed request or ID (code: validation_error | invalid_json)
- `401`: The API key is missing or not valid. See [Authentication](https://docs.scrip.dev/authentication).
- `403`: The caller is not allowed to do this.
- `404`: Program not found (code: program_not_found)
- `409`: The key is taken, another request placed a rule set at the same time, or the program is archived (code: rule_set_key_already_exists | rule_set_order_conflict | program_archived)
- `422`: The key or name is not valid, or position.reference_id is not in the program (code: invalid_rule_set | invalid_position)
- `429`: Too many requests. Wait the number of seconds in the `Retry-After` header, then retry. See [Limits and durations](https://docs.scrip.dev/limits#rate-limits).
- `500`: Something failed on Scrip's side. Retry the request, and quote `request_id` if it keeps failing. [Errors](https://docs.scrip.dev/errors) lists every code, and the [API introduction](https://docs.scrip.dev/api-reference/introduction) describes the error format.

---

[API](https://skmtc.dev/scrip/apis/scrip-api.md) · [All operations](https://skmtc.dev/scrip/apis/scrip-api/llms.txt) · [OpenAPI document](https://skmtc.dev/scrip/apis/scrip-api/revisions/c52d35da8d97?raw)
