---
title: "Evaluate"
method: POST
path: "/v25-10-beta/agentic-logic/evaluate"
tags: ["Agentic Logic"]
---

# Evaluate

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

## Request

- Base URL: `https://api.intelligems.io`
- URL: `https://api.intelligems.io/v25-10-beta/agentic-logic/evaluate`
- 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/evaluate/post.ts> (a function with typed inputs; its response is checked against the schema)

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

Evaluates the active rule assigned to a placement without changing rule or
placement state. It returns evaluation
telemetry, and does not record an impression.

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

- object: Run one evaluation against a supplied request context and return the versioned result envelope. Metered per organization; never recorded as an impression. The result never holds more than the slot count and already reflects the rule's exclusion settings, out of stock included.
  - `request` object, required: The full serving request envelope. `placementId` must be an API-created placement with an enabled assignment; `surface` declares the surface your rendering context corresponds to.
    - `surface` 'onsite' | 'checkout' | 'post-purchase', required: Surface the recommendation will render on. There is deliberately no 'headless' value — API callers declare the surface they render.
    - `placementId` string, required: Identifier of the placement being filled.
    - `cart` object, nullable, required: Snapshot of the visitor's current cart. An empty cart (zero lines) is a legal cart — distinct from cart: null, which means the surface has no cart at all (post-purchase).
      - `currency` string, required: ISO-4217 currency code all money fields in this cart are in.
      - `subtotal` integer, required: Cart merchandise subtotal in integer minor units of `currency`, before shipping and taxes.
      - `itemCount` integer, required: Total unit quantity across all lines (sum of line quantities) — units, not the count of distinct lines.
      - `lines` object[], required: The cart lines.
        - `productId` string, required: Shopify product GID (gid://shopify/Product/<n>). The bare numeric id the Shopify admin and most PIM exports show is accepted and promoted to GID form on the way in; anything that is neither is rejected.
        - `variantId` string, required: Shopify variant GID (gid://shopify/ProductVariant/<n>). The bare numeric id the Shopify admin and most PIM exports show is accepted and promoted to GID form on the way in; anything that is neither is rejected.
        - `quantity` integer, required: Number of units on the line. Positive integer.
        - `unitPrice` integer, required: Per-unit price actually in the cart, in integer minor units of the cart's currency.
        - `lineTotal` integer, required: Line total (unit price times quantity, after line-level adjustments), in integer minor units of the cart's currency.
        - `selectedOptions` object[], required: Selected product options for the line's variant.
          - `name` string, required: Option name as configured on the Shopify product (e.g. 'Size').
          - `value` string, required: Selected option value (e.g. 'Medium').
        - `isSubscriptionLine` boolean, required: True when the line carries a selling plan (subscription), false for a one-time purchase.
        - `flags` object, required: Provenance flags (gift card, synthetic gift, bundle child, Intelligems upsell). Which flags a surface can actually answer differs per surface — see the request contract's per-surface caveats.
          - `giftCard` boolean, nullable, required: True when the line is a Shopify gift-card product, false when known not to be one, or null when the surface exposes no authoritative marker. NULL on every checkout and post-purchase line — neither surface exposes a gift-card marker, so a clause keyed on this flag is inert there.
          - `syntheticGift` boolean, nullable, required: True when the line was injected as a gift-with-purchase by a promotion, false when known not to be one, or null when the surface exposes no authoritative marker.
          - `bundleChild` boolean, nullable, required: True when the line is a child component of an expanded bundle, false when known not to be one, or null when the surface exposes no authoritative marker. NULL on every post-purchase line, and never `true` onsite — `/cart.js` does not list bundle component lines at all.
          - `igUpsell` boolean, nullable, required: True when the line was added by an Intelligems upsell, false when known not to be one, or null when the surface exposes no authoritative marker.
        - `tags` string[]: The line product's Shopify tags, hydrated ONLY when an evaluated rule targets on tags — absent otherwise. Absent means 'not looked up' and an empty array means 'looked up, none'; the two are never interchangeable, and a rule reading an absent value must fail loudly rather than treat it as no tags.
        - `collections` string[]: Shopify collection GIDs the line product belongs to, hydrated ONLY when an evaluated rule targets on collections — absent otherwise. Bare numeric collection ids are accepted and promoted to GID form on the way in. Same absent-vs-empty rule as `tags`.
    - `order` object, nullable, required: The completed order a post-purchase surface is rendered against. First-class on the post-purchase surface only; null everywhere else. Deliberately carries NO customer field — the top-level request `customer` is the single customer reference.
      - `orderId` string, required: Shopify order GID (gid://shopify/Order/<n>).
      - `checkoutToken` string: Shopify checkout token for the checkout that produced this order, when available.
      - `createdAt` string, date-time, required: Order creation time as an ISO-8601 UTC timestamp.
      - `currencyCode` string, required: ISO-4217 shop currency code the order's money fields are denominated in.
      - `presentmentCurrency` string, required: ISO-4217 currency code the shopper saw at checkout, which may differ from `currencyCode`.
      - `itemsSubtotal` integer, required: Merchandise subtotal after line-level discounts but before order-level discounts, shipping, and taxes. Integer minor units.
      - `discountTotal` integer: Total order-level discount amount in integer minor units, when any.
      - `shippingTotal` integer: Shipping charged in integer minor units, when known.
      - `taxTotal` integer: Taxes charged in integer minor units, when known.
      - `total` integer, required: What the shopper was actually charged, in integer minor units.
      - `lines` object[], required: The purchased order lines.
        - `productId` string, required: Shopify product GID (gid://shopify/Product/<n>). The bare numeric id the Shopify admin and most PIM exports show is accepted and promoted to GID form on the way in; anything that is neither is rejected.
        - `variantId` string, required: Shopify variant GID (gid://shopify/ProductVariant/<n>). The bare numeric id the Shopify admin and most PIM exports show is accepted and promoted to GID form on the way in; anything that is neither is rejected.
        - `quantity` integer, required: Number of units on the line. Positive integer.
        - `unitPrice` integer, required: Per-unit price actually in the cart, in integer minor units of the cart's currency.
        - `lineTotal` integer, required: Line total (unit price times quantity, after line-level adjustments), in integer minor units of the cart's currency.
        - `selectedOptions` object[], required: Selected product options for the line's variant.
          - `name` string, required: Option name as configured on the Shopify product (e.g. 'Size').
          - `value` string, required: Selected option value (e.g. 'Medium').
        - `isSubscriptionLine` boolean, required: True when the line carries a selling plan (subscription), false for a one-time purchase.
        - `flags` object, required: Provenance flags (gift card, synthetic gift, bundle child, Intelligems upsell). Which flags a surface can actually answer differs per surface — see the request contract's per-surface caveats.
          - `giftCard` boolean, nullable, required: True when the line is a Shopify gift-card product, false when known not to be one, or null when the surface exposes no authoritative marker. NULL on every checkout and post-purchase line — neither surface exposes a gift-card marker, so a clause keyed on this flag is inert there.
          - `syntheticGift` boolean, nullable, required: True when the line was injected as a gift-with-purchase by a promotion, false when known not to be one, or null when the surface exposes no authoritative marker.
          - `bundleChild` boolean, nullable, required: True when the line is a child component of an expanded bundle, false when known not to be one, or null when the surface exposes no authoritative marker. NULL on every post-purchase line, and never `true` onsite — `/cart.js` does not list bundle component lines at all.
          - `igUpsell` boolean, nullable, required: True when the line was added by an Intelligems upsell, false when known not to be one, or null when the surface exposes no authoritative marker.
        - `tags` string[]: The line product's Shopify tags, hydrated ONLY when an evaluated rule targets on tags — absent otherwise. Absent means 'not looked up' and an empty array means 'looked up, none'; the two are never interchangeable, and a rule reading an absent value must fail loudly rather than treat it as no tags.
        - `collections` string[]: Shopify collection GIDs the line product belongs to, hydrated ONLY when an evaluated rule targets on collections — absent otherwise. Bare numeric collection ids are accepted and promoted to GID form on the way in. Same absent-vs-empty rule as `tags`.
        - `title` string: Product title at purchase time, when available.
        - `vendor` string: Product vendor at purchase time, when available.
        - `productType` string: Shopify product type at purchase time, when available.
        - `sellingPlanId` string: Shopify selling-plan GID (gid://shopify/SellingPlan/<n>) when the line was purchased on a subscription.
        - `discountAllocations` object[]: Line-level discount allocations applied to this line, when any.
          - `amount` integer, required: Discount amount allocated to the line, in integer minor units of the order's currency.
          - `title` string: Discount title or code as shown on the order, when available.
    - `pageProduct` object, nullable, required: The product a PDP placement is rendered on. Populated for onsite product-page placements only; null everywhere else.
      - `productId` string, required: Shopify product GID of the product being viewed (gid://shopify/Product/<n>). The bare numeric id the Shopify admin shows is accepted and promoted to GID form on the way in; anything that is neither is rejected.
      - `handle` string, required: Shopify product handle (URL slug) of the product being viewed.
      - `targeting` object, nullable: Theme product facts used for onsite product targeting. Null when the theme has no product data; product-targeted branches then do not match. Absent from clients that predate the field; serving then reads the facts from Shopify when the rule targets the product.
        - `tags` string[], required
        - `collectionIds` integer[], required
        - `inventory` integer, required
        - `lowestVariantPrice` integer, required
    - `customer` object, nullable, required: Minimal identified-customer context, or null for guests. PII-MINIMAL GUARANTEE: this object carries ids, counts, and money aggregates ONLY — no email, name, phone, or address field may ever be added here. That is a contract property, not a data-availability accident; richer profile data is fetched at rule runtime via sdk.getCustomer().
      - `id` string, required: Shopify customer GID (gid://shopify/Customer/<n>).
      - `ordersCount` integer, nullable, required: Number of orders this customer has placed, or null when the surface did not supply it — checkout supplies it for a verified buyer when the app's protected-customer-data grant covers it; onsite and post-purchase never do. Integer, >= 0, when present. Null-check it, or use sdk.getCustomer() for a count that does not depend on the grant.
      - `amountSpent` object: Lifetime spend aggregate, when known.
        - `amount` integer, required: Lifetime amount spent in integer minor units of `currency`.
        - `currency` string, required: ISO-4217 currency code `amount` is denominated in.
    - `shipping` object, required: Shipping-incentive context. Required — 'not-applicable' is expressed in-band via its state field, never by omitting the object.
      - `state` 'resolved' | 'assumed' | 'not-applicable' | 'unavailable', required: 'resolved' = thresholds are known facts for this visitor; 'assumed' = best-effort defaults that may be wrong, so treat them as a hint rather than a fact when steering; 'not-applicable' = the store has no shipping incentive here, and the order may not be shipping at all; 'unavailable' = the shipping facts could not be read before the serving deadline (a Shopify read failed or timed out), so no threshold field is present and nothing is known — never read it as 'no incentive'.
      - `currency` string, required: ISO-4217 currency code the threshold fields are denominated in. Always present, even when state is 'not-applicable'.
      - `freeShippingThreshold` integer: Cart subtotal at which shipping becomes free, in integer minor units — pre-resolved to the visitor's assigned variation's threshold. Absent when there is no free-shipping incentive.
      - `remainingToFreeShipping` integer, nullable: How much more the visitor must add to qualify for free shipping, in integer minor units. 0 = already qualifies; absent or null = unresolvable.
      - `tiers` object[]: Tiered incentive ladder in ascending threshold order, when the store runs tiered incentives.
        - `threshold` integer, required: Cart subtotal at which this tier unlocks, in integer minor units of the shipping context's currency.
        - `label` string, required: Shopper-facing label for the tier (e.g. 'Free shipping').
      - `delivery` object: The delivery options Shopify computed for this checkout, as observed facts rather than merchant settings. Present only at checkout, and only once Shopify has computed options (an address or a pickup selection exists); absent onsite, post-purchase, and on first render. Present under every state, including 'not-applicable' for local pickup.
        - `isLocalPickup` boolean, required: True when every selected delivery option is a pickup option — the buyer is not shipping anything.
        - `selected` object: The buyer's currently selected option, when exactly one delivery group has a selection. Absent before the buyer picks, and when multiple groups (a subscription plus a one-time purchase) select different options — read `options` then.
          - `title` string: Shopper-facing option title, when Shopify reports one.
          - `isPickup` boolean, required: True for a pickup option (pickup point or pickup location) rather than a shipping rate. Pickup options carry no cost and no transit estimate.
          - `selected` boolean, required: True when this is the buyer's currently selected option in its delivery group.
          - `cost` integer: The option's cost after shipping discounts, in integer minor units of `currency`. 0 = free. Absent on pickup options, which have no cost.
          - `currency` string: ISO-4217 currency code of `cost`. Absent with it.
          - `carrierName` string: Carrier presenting the option, when Shopify reports one.
          - `transitDays` object: Estimated time in transit in whole days, when Shopify reports one — `min` rounded down, `max` rounded up. Shipping options only.
            - `min` integer
            - `max` integer
        - `options` object[], required: Every option Shopify computed, flattened across delivery groups, in Shopify's order. A zero-cost non-pickup option means the buyer already qualifies for free shipping.
          - `title` string: Shopper-facing option title, when Shopify reports one.
          - `isPickup` boolean, required: True for a pickup option (pickup point or pickup location) rather than a shipping rate. Pickup options carry no cost and no transit estimate.
          - `selected` boolean, required: True when this is the buyer's currently selected option in its delivery group.
          - `cost` integer: The option's cost after shipping discounts, in integer minor units of `currency`. 0 = free. Absent on pickup options, which have no cost.
          - `currency` string: ISO-4217 currency code of `cost`. Absent with it.
          - `carrierName` string: Carrier presenting the option, when Shopify reports one.
          - `transitDays` object: Estimated time in transit in whole days, when Shopify reports one — `min` rounded down, `max` rounded up. Shipping options only.
            - `min` integer
            - `max` integer
    - `country` string, nullable: OPTIONAL. ISO-3166-1 alpha-2 code of the market this request should be evaluated in, e.g. 'CA'. Omit it (or send null) and the platform evaluates in its default market, 'US'. Name it whenever the cart is denominated in a non-shop currency, so the catalog reads run in the same market the money does.
    - `cartFingerprint` string: Opaque client-supplied fingerprint of the cart state this request was built from. The engine echoes it verbatim on the result envelope so the rendering surface can compare and discard late results.
  - `slotsNeeded` integer, required: How many recommendation slots the caller intends to render. Non-negative integer, at most 50. Zero is legal and asks the rule for an empty result; it is not an error.
  - `visitorId` string: Seed for the deterministic shuffle (with the rule version). Omitted = a fresh random id per call. Pass a fixed value to make repeat calls comparable against pinned fixtures; live results still drift with the catalog.
  - `country` string, required: ISO 3166-1 alpha-2 country the evaluation should price and read Storefront data for.
  - `variationId` string, uuid, nullable: Experiment cell to resolve the assignment in. Null or omitted = the placement's global cell. A named variation resolves its own enabled cell when it has one, and otherwise falls back to the global cell — a disabled variation cell does not suppress the global default.

## Response `200`

OK

- object: The evaluation result: the versioned envelope plus its telemetry facts.
  - `result` object, required: The versioned result envelope and evaluation telemetry. `telemetry.evaluationSource` is 'api' on this endpoint.
    - `envelope` object, required: What a recommendation rule returns. Conventions: ids are Shopify GIDs; money is integer minor units with explicit ISO-4217 currency; timestamps are ISO-8601 UTC. Engine errors and timeouts collapse to an empty result behaviorally (the surface follows the placement's onEmpty policy) but stay distinct in evaluation telemetry.
      - `version` 1, required: Envelope schema version. Activating any reserved shape bumps this version — consumers negotiate on it, it never breaks silently. Independent of the REST API path version.
      - `items` object[], required: Recommended items in render order. An empty array is a valid result — a miss, not an error.
        - `kind` 'product' | 'variant' | 'image' | 'reviewRef' | 'metaobjectRef' | 'bundle', required: Item kind. Consumers ignore kinds they don't understand — never errors.
        - `id` string, required: Shopify GID of the recommended entity, scoped by `kind` (e.g. gid://shopify/Product/<n> for kind 'product'). For kind 'bundle' the id is the Product GID of the bundle's parent/anchor product, never a merchant-chosen key — there is no gid://shopify/Bundle/<n>.
        - `defaultVariantId` string: Which variant is pre-selected for the shopper — the core output for product-kind items, so surfaces render a purchasable default without re-deriving one.
        - `allowedVariantIds` string[]: Exhaustive list of variant GIDs the shopper may add, when the merchant restricted the item to a subset of its variants. ABSENT means unrestricted (every variant is allowed); present means only these are. Surfaces that mint per-variant discount signatures MUST sign only these — treating absence and an empty list alike would mint a signature for a variant the merchant excluded.
        - `sellingPlanId` string: Shopify selling-plan GID to attach when the item is added, for subscription recommendations. RESERVED in V1.
        - `intent` 'add' | 'replace': 'add' adds the item to the cart. 'replace' asks the surface to swap out the originating cart line and is materialized by NO surface today — emitting it is refused at publish rather than silently downgraded, because a surface that can only Add would put the swap target alongside the item it was meant to replace. Recommend the swap target with intent 'add', or wait for a surface that supports it. RESERVED in V1.
        - `discount` object: RESERVED in V1 and read by NO surface — setting it prices nothing, and it is REFUSED at ingress. Pricing is the placement's, never the rule's. Activating this field bumps the envelope version.
          - `type` 'percentage' | 'fixed', required: 'percentage' or 'fixed'.
          - `value` number, required: For 'percentage': percent points (10 = 10% off). For 'fixed': integer minor units in the shop currency.
        - `sourceBranch` string: Path-capable label of the rule branch that produced this item (e.g. 'colour-match/size-in-stock'), for telemetry and debugging.
        - `children` object[]: Child lines when kind is 'bundle'. Each child's `id` must match its own `kind` — a 'product' child carries a Product GID, a 'variant' child a ProductVariant GID. Schema-level tolerance: presence on other kinds is a gate concern, not a parse error.
          - `kind` 'product' | 'variant' | 'image' | 'reviewRef' | 'metaobjectRef' | 'bundle', required: Kind of the child item (scopes how `id` is interpreted).
          - `id` string, required: Shopify GID of the child, scoped by `kind`.
          - `quantity` integer, required: Units of the child included in the bundle. Positive integer.
      - `branchFired` object: The terminal rule branch that produced this result.
        - `base` string, required: The literal label passed to attempt('label') in the rule source — statically lexable, so publish gates can verify it exists in the code.
        - `instance` string: Runtime instance qualifier when one branch runs multiple passes (e.g. the tag this pass ran against). Present ONLY when the attempt supplied one via `attempt(base, fn, { instance })`; the key is omitted entirely otherwise, so consumers must treat its absence as normal and must never assert deep equality against an object that assumes it.
      - `cartFingerprint` string: Echo of the request's cartFingerprint, verbatim. The rendering surface compares it against the current cart state and discards late results that no longer match.
      - `warnings` string[]: Non-fatal notices from the evaluation, surfaced to telemetry and debugging tools.
      - `metadata` object: Rule-authored metadata. Free-form and read by NOTHING — no key here is interpreted. A rule decides WHICH products are recommended; it never prices them. The discount and the struck-through price belong to the placement the rule is attached to, where the merchant sets them.
    - `telemetry` object, required: Telemetry facts for one rule evaluation. Emission is the broker's job; the shape is typed here so the vocabulary is pinned with the envelope. Errors and timeouts collapse to empty behaviorally (the surface follows the placement's onEmpty policy) but stay distinct here.
      - `outcome` 'result' | 'empty' | 'error', required: 'result' = items returned; 'empty' = valid miss (zero items); 'error' = the evaluation failed or timed out and the surface fell back to empty behavior.
      - `errorClass` string: Free-form classifier of the failure when outcome is 'error'. Deliberately not an enum yet — the vocabulary gets pinned once real failure modes exist.
      - `datasetRevisions` object[]: The dataset revisions the evaluation's pinned reads resolved to, one entry per distinct key read. This is the field the impression stamp records (persistence lands with the impression store, M4).
        - `key` string, required: The dataset key the evaluation read.
        - `revision` integer, required: The revision the evaluation's pinned read resolved to.
      - `removedByExclusion` object[]: Items removed by serving exclusions, with only the item id and the approved removal reason.
        - `itemId` string, required
        - `reason` 'product_id' | 'tag' | 'collection' | 'vendor' | 'metadata_unavailable', required
      - `attempts` object[]: Per-attempt chain records in execution order, captured by the SDK runtime's accumulator — never authored by rule code. Fallback rate = attempt 1 contributed 0. Absent means no chain ran, never 'zero attempts'.
        - `base` string, required: The attempt's stable base label (e.g. 'colour-match').
        - `instance` string: Per-invocation instance qualifier (e.g. the seed product handle) for readout grouping. Present ONLY when the attempt supplied one via `attempt(base, fn, { instance })`; the key is omitted entirely otherwise, so consumers must treat its absence as normal and must never assert deep equality against a record that assumes it.
        - `contributed` integer, required: How many of this attempt's items made the final result. Non-negative integer.
        - `outcome` 'contributed' | 'empty' | 'not-selected' | 'skipped' | 'error', required: 'contributed' | 'empty' | 'not-selected' | 'skipped' | 'error' — see AgenticLogicAttemptOutcomeList for exact semantics.
      - `evaluationSource` 'serving' | 'api' | 'preview': Which lane produced this evaluation: 'serving' = a shopper-facing surface, 'api' = the metered external/MCP evaluate endpoint, 'preview' = authoring preview. 'api' and 'preview' evaluations are never impressions — readouts must exclude them.
      - `executionTier` 'template' | 'custom': Which executor ran the rule: 'template' = the shared warm template runner, 'custom' = the org's own rule Lambda. Absent when the evaluation exited before an assignment resolved, so nothing ran. Not the same vocabulary as the stored version execution kind.
      - `deadlineMs` integer: The RELATIVE time budget the evaluation ran under, in milliseconds — min(surface hard cap, the assignment's budgetMs). The absolute epoch deadline is meaningless in a readout and already rides the invocation as system.deadlineAtMs. Absent when the evaluation exited before an assignment resolved.
      - `fallback` 'not-applicable' | 'hidden' | 'materialized' | 'unavailable' | 'failed': What the placement's onEmpty policy did with an empty rule result: 'not-applicable' = the rule returned items, so no policy ran; 'hidden' = onEmpty is 'hide'; 'materialized' = the smart-recs fallback supplied the items; 'unavailable' = smart-recs was asked and had nothing to give; 'failed' = the fallback read itself errored. This is what separates empties a readout would otherwise collapse into one bucket.
      - `classifierBreakerTripped` boolean: Whether the org-scoped storefront-classifier breaker was already open when this evaluation started, so the rule was short-circuited rather than executed. Absent when the evaluation exited before the breaker was consulted.

## 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/evaluate/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)
