OfferKitDocs

Rule inputs and operators

Write OfferKit validation rules using the data each decision receives, check operator boundaries, and avoid conditions that cannot match at runtime.

A rule is a JSON Logic expression: a JSON object whose key is an operator and whose values are its arguments. {"var":"order.amount"} reads the submitted order amount. {">=":[{"var":"order.amount"},5000]} means at least 5000 minor units.

Start with Target customers with rules for examples you can adapt.

Available facts

FactVoucher validation, redemption, and qualificationPromotion qualificationSegment preview
customer.id, email, name, phone, addressFrom the resolved stored customerFrom the stored customer selected by UUIDFrom each of the up to 10,000 most recent customers being evaluated
customer.metadataStored customer metadataStored customer metadataStored customer metadata
customer.summaryStored summaryStored summaryStored summary
order.amount, currency, itemsFrom inline order, when suppliedFrom the required inline orderNo order
voucher.id, voucher.codeThe voucher being checkedUnavailableUnavailable
nowServer time as an ISO timestampServer time as an ISO timestampPreview time as an ISO timestamp
metadataEmpty object; there is no request-metadata inputRequest-level metadataEmpty object
customer.segmentsNot populatedNot populatedEmpty array
customer.loyalty, redemptionsByCustomerNot populated by these decision pathsNot populatedNot populated

Do not infer a fact from a variable name in the rule builder. For example, customer.in_segment cannot match a segment in these paths because segment membership has not been loaded. redemption.count_for_customer_above defaults to zero when its fact is unavailable. Use only facts the call actually supplies.

The stored summary shape includes totalSpent, redemptionCount, and lastRedeemedAt, but normal customer APIs do not let you set it and the runtime does not maintain it. It stays empty for customers created through those APIs. Put application-owned facts such as lifetime spend in customer metadata and sync them from your commerce system.

Operators

Standard JSON Logic operators include and, or, !, ==, ===, >, >=, <, <=, var, and missing. The visual builder covers a subset. Raw JSON uses the same JSON Logic syntax.

OfferKit adds these operators:

ExpressionMeaning
{"order.contains_product":["sku-shirt"]}At least one submitted item has this productId.
{"order.contains_collection":["summer"]}At least one submitted item has this collectionId.
{"order.total_above":[5000,"USD"]}Order amount is strictly greater than 5000 and currency is USD. Exactly 5000 fails.
{"date.between":["2026-11-01T00:00:00Z","2026-11-30T23:59:59Z"]}Server time falls within the inclusive timestamp range.
{"customer.in_segment":["segment-uuid"]}Tests supplied membership; normal decision calls do not populate it.
{"redemption.count_for_customer_above":[2]}Tests a preloaded count; normal decision calls do not populate it.

For an inclusive minimum, use >= rather than order.total_above. Include the currency condition separately when using a numeric comparison.

Missing data and errors

JSON Logic does not treat every missing fact as a configuration error. A missing value can become false, null, or a default used by the expression. Require the facts you need:

{
  "and": [
    { "!!": [{ "var": "customer.id" }] },
    { "===": [{ "var": "customer.metadata.vip" }, true] }
  ]
}

Test a passing value, a failing value, a missing value, and an unexpected type. An unknown operator produces an evaluation error. Voucher decisions report rule failures as validation_failed; promotions distinguish rule_failed from rule_error.

Product and collection conditions decide whether an offer may apply. They do not reduce the discount base to matching items. The current discount calculator uses the submitted order.amount and does not apply the discount.appliesTo item filter. Do not promise a line-item discount based on that field.