---
title: "Create a rule"
method: POST
path: "/v25-10-beta/agentic-logic/rules"
tags: ["Agentic Logic"]
---

# Create a rule

`POST /v25-10-beta/agentic-logic/rules`

## Request

- Base URL: `https://api.intelligems.io`
- URL: `https://api.intelligems.io/v25-10-beta/agentic-logic/rules`
- Auth: API key in header `intelligems-access-token`
- TypeScript: <https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/docs/v25-10-beta/agentic-logic/rules/post.ts> (a function with typed inputs; its response is checked against the schema)

```http
POST /v25-10-beta/agentic-logic/rules
```

Creates a rule in the `draft` state. The response is `{ rule }`.

- `name` (string, required) — Merchant-facing rule name.
- `description` (string, required, 1–1024 characters) — Plain-language summary
  of what the rule recommends, in what order, and for which shoppers.
- `managedBy` (string, required) — `builder` for a template-configured rule, or
  `code` for a rule whose source you author through the draft endpoint. Fixed
  after creation.
- `settings` (object, optional) — Recommendation settings: `maxItems` (1–10),
  `excludeOutOfStock`, `excludeItemsInCart`, and `onEmpty` (`hide` or
  `smart-recs`), all required when the object is sent. Omit it to take the
  defaults: 3 items, both exclusions on, `hide`.

A builder rule also takes:

- `templateId` (string, required) — Template to configure.
- `templateParams` (object, optional) — Validated against the template's
  params schema.
- `templateVersion` (number, optional) — Template version the params were
  written against.

Builder rules don't take `targetSurfaces`; their template sets the surfaces.

A code rule also takes:

- `targetSurfaces` (string array, required) — The surfaces (`onsite`,
  `checkout`, `post-purchase`) whose placements the rule may be assigned to.
  Non-empty, with no repeats, and fixed after creation.
- `authoringSessionId` (string, optional) — The AI chat session authoring the
  rule.

A code-rule body is strict: unknown fields are rejected.

Creating a builder rule starts its first publish. A code rule needs a saved
draft before it can publish (see [Save a code rule's draft](#save-a-code-rules-draft)).
A rule serves nothing until it has an active version and is assigned to a
placement.

Use the `intelligems-access-token` header. The token selects the organization; do not send `orgId`. The organization must have Agentic Logic enabled.

**Rate Limit:** 50 requests per 30s window, refilling 25 tokens every 30s.

## Request body

- union: Create a rule container (state starts at 'draft').
  - object
    - `name` string, required: Merchant-facing rule name.
    - `description` string, required: Plain-language summary of what the rule recommends, in what order, and for which shoppers.
    - `settings` object: The rule's recommendation settings. Optional: omit to take the defaults (3 items, both exclusions on, hide when empty), which is what a merchant who never mentions them should get.
      - `maxItems` integer: Most products the rule may return, 1-10. The engine supplies it to the rule as `context.slotsNeeded` and trims the envelope to it. One bound for every surface, because one rule can serve several. A surface may still show fewer at once: the checkout block's grid paginates the returned list into a carousel, which is presentation and stays with the placement.
      - `excludeOutOfStock` boolean: Drop products with no purchasable variant. Applied where the product data already is: inside the template for a builder rule, inside the generated source for a code rule, and again as a floor when the engine hydrates the result — so the setting is true on every surface rather than only the ones that remembered to pass it.
      - `excludeItemsInCart` boolean: Drop products the shopper already has in the cart. Runs before the emptiness test, so an envelope this empties falls through to `onEmpty` rather than reporting itself as a result.
      - `excludePdpProduct` boolean: Drop the product the shopper is viewing (`request.pageProduct`, PDP only). Applied inside builder templates before the item cap, so the slot backfills, and again by the engine on every rule's result. Turn it off when the viewed product belongs in the result, e.g. a bundle built around it.
      - `onEmpty` 'hide' | 'smart-recs': What the slot does when the rule returns zero items: 'hide' the placement or fall back to 'smart-recs'. Errors and timeouts take the same route as a miss — there is no separate error policy — and stay distinct in telemetry.
    - `managedBy` 'builder', required: 'builder' or 'code'. Immutable after creation.
    - `templateId` string, required: Template id for builder rules. Required when managedBy is 'builder'.
    - `templateParams` object: Template params for builder rules, validated against the template's params schema at write time.
    - `templateVersion` integer: Template artifact version the params were authored against.
  - object
    - `name` string, required: Merchant-facing rule name.
    - `description` string, required: Plain-language summary of what the rule recommends, in what order, and for which shoppers.
    - `settings` object: The rule's recommendation settings. Optional: omit to take the defaults (3 items, both exclusions on, hide when empty), which is what a merchant who never mentions them should get.
      - `maxItems` integer: Most products the rule may return, 1-10. The engine supplies it to the rule as `context.slotsNeeded` and trims the envelope to it. One bound for every surface, because one rule can serve several. A surface may still show fewer at once: the checkout block's grid paginates the returned list into a carousel, which is presentation and stays with the placement.
      - `excludeOutOfStock` boolean: Drop products with no purchasable variant. Applied where the product data already is: inside the template for a builder rule, inside the generated source for a code rule, and again as a floor when the engine hydrates the result — so the setting is true on every surface rather than only the ones that remembered to pass it.
      - `excludeItemsInCart` boolean: Drop products the shopper already has in the cart. Runs before the emptiness test, so an envelope this empties falls through to `onEmpty` rather than reporting itself as a result.
      - `excludePdpProduct` boolean: Drop the product the shopper is viewing (`request.pageProduct`, PDP only). Applied inside builder templates before the item cap, so the slot backfills, and again by the engine on every rule's result. Turn it off when the viewed product belongs in the result, e.g. a bundle built around it.
      - `onEmpty` 'hide' | 'smart-recs': What the slot does when the rule returns zero items: 'hide' the placement or fall back to 'smart-recs'. Errors and timeouts take the same route as a miss — there is no separate error policy — and stay distinct in telemetry.
    - `managedBy` 'code', required: 'builder' or 'code'. Immutable after creation.
    - `targetSurfaces` string[], required: Surfaces this code rule is written for, and the only surfaces whose placements it may later be assigned to. Required for code rules, refused for builder rules, and immutable once set. Choose from the surfaces that can supply the request context the rule reads: post-purchase has an order and no cart, onsite has no customer identity, checkout has no page product.
    - `authoringSessionId` string: Id of the AI chat session authoring this rule. Optional: a rule created outside a chat omits it. A later authoring session repoints it, so the workspace always loads back the conversation that explains the rule's current state.

## Response `200`

OK

- object
  - `rule` object, required: One recommendation rule: the org-scoped container that owns drafts, immutable versions, and placement assignments. The rule row carries lifecycle state; only 'active' rules are evaluable.
    - `id` string, required: Server-issued rule id (uuid).
    - `organizationId` string, required: Owning organization id (uuid).
    - `name` string, required: Merchant-facing rule name.
    - `description` string, required: Plain-language summary of what the rule recommends, in what order, and for which shoppers.
    - `managedBy` 'builder' | 'code', required: 'builder' = configured from a template (templateId + templateParams + templateVersion); 'code' = a custom-code workspace rule.
    - `state` 'draft' | 'active' | 'paused', required: Lifecycle state: draft → active → paused. Paused renders as rule-absent on serving. Retiring a rule is a hard delete, legal from any state but never while referenced.
    - `templateId` string, nullable, required: Template identifier for builder rules; null for code rules.
    - `templateParams` object, nullable, required: Template parameters for builder rules, validated against the template's params schema at write time; null for code rules.
    - `templateVersion` integer, nullable, required: Template artifact version the rule was configured against (echo-on-execute model); null for code rules.
    - `targetSurfaces` string[], nullable, required: Surfaces a code rule declares it is written for, fixed at creation and never editable; the rule may only be assigned to placements on these surfaces. Null for builder rules, whose eligibility comes from their template instead. Declared, never inferred: it states which request context the rule was written against, since a surface cannot supply data it never has (post-purchase has no cart, onsite has no customer).
    - `settings` object, required: The rule's recommendation settings — item cap, the two product exclusions, and the empty-result policy. The EDITABLE copy: serving reads the copy frozen onto the active version, so changing this changes nothing until the rule is republished.
      - `maxItems` integer, required: Most products the rule may return, 1-10. The engine supplies it to the rule as `context.slotsNeeded` and trims the envelope to it. One bound for every surface, because one rule can serve several. A surface may still show fewer at once: the checkout block's grid paginates the returned list into a carousel, which is presentation and stays with the placement.
      - `excludeOutOfStock` boolean, required: Drop products with no purchasable variant. Applied where the product data already is: inside the template for a builder rule, inside the generated source for a code rule, and again as a floor when the engine hydrates the result — so the setting is true on every surface rather than only the ones that remembered to pass it.
      - `excludeItemsInCart` boolean, required: Drop products the shopper already has in the cart. Runs before the emptiness test, so an envelope this empties falls through to `onEmpty` rather than reporting itself as a result.
      - `excludePdpProduct` boolean, required: Drop the product the shopper is viewing (`request.pageProduct`, PDP only). Applied inside builder templates before the item cap, so the slot backfills, and again by the engine on every rule's result. Turn it off when the viewed product belongs in the result, e.g. a bundle built around it.
      - `onEmpty` 'hide' | 'smart-recs', required: What the slot does when the rule returns zero items: 'hide' the placement or fall back to 'smart-recs'. Errors and timeouts take the same route as a miss — there is no separate error policy — and stay distinct in telemetry.
    - `authoringSessionId` string, nullable, required: Id of the AI chat session that most recently authored this rule, or null for a rule created outside a chat (and for every rule created before the association was recorded). Follows the latest authoring conversation: creating the rule sets it, and a later revision session repoints it, so the transcript the workspace loads back after a reload — including the diagnosis of a build that gave up — is the one that explains the rule's current state.
    - `systemKey` 'shopify-recommendations', nullable: Set only on a built-in rule Intelligems provisions for every store (e.g. 'shopify-recommendations'); null or absent on every rule a merchant or Atlas created. A built-in rule is read-only: it cannot be renamed, edited, paused, resumed or deleted, and there is at most one per key per store.
    - `createdAtTs` number, required: Creation time, Unix epoch-ms.
    - `lastUpdateTs` number, required: Last update time, Unix epoch-ms.

## Other responses

- `429`: Too Many Requests

## Changes

- **2026-11-06** `7b769b2f90b1`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/changes/v25-10-beta/agentic-logic/rules/post.md)

---

[API](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta.md) - [All operations](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/llms.txt) - [OpenAPI document](https://skmtc.dev/intelligems/apis/intelligems-external-api-v25-10-beta/revisions/7b769b2f90b1?raw)
