Skip to content

    Pre-launch API. The concepts described here are settled, but the API shape is not: request and response fields, parameters and defaults can still change. Build against it, and talk to your Luigi's Box contact before you put an integration into production.

    Business rules

    View source

    Ranking answers most questions well. Business rules are for the ones it cannot know about: the supplier deal that has to be visible this week, the discontinued line that must stop appearing, the hero product on the sale page.

    A rule does not replace ranking. It is applied inside it — the results are still ranked, and the rule adjusts the outcome. That is why the rules you write and the ranking you did not configure can coexist without one flattening the other.

    A rule names the products it acts on, by ID or by criteria such as a brand or a clearance flag, and one of four effects. pin fixes a position. ban removes. boost and bury shift the ranking, at full strength or fading over time.

    Rules are grouped into campaigns. A campaign answers three questions, and each rule inside it answers a fourth:

    QuestionWhere it lives
    TargetingWhich catalogs, channels, surfaces and intents does this apply to?Campaign
    TriggerWhich requests does it fire on?Campaign match
    ScheduleWhen does it run?Campaign starts_at / ends_at
    EffectWhich products, and what happens to them?Each rule

    Targeting has a permissive default: a dimension you leave empty means all of it. The trigger is always present, and a campaign with no schedule runs whenever it is active.

    A campaign holds 1–50 rules and belongs to one organization. Its name must be unique among the organization’s live campaigns.

    “Product” on these pages stands for any catalog object the surface serves. The same rules apply to categories, brands or articles; an ID such as category/shoes names the type.

    What a campaign is made ofA campaign holds targeting, a trigger, a schedule and between one and fifty rules; each rule applies one effect to the objects it selects.CampaignTargetingcatalogs, channels, surfaces, intentsTriggerwhich requestsSchedulewhenRules1–50 per campaignEffectwhich objects · pin, ban, boost, bury

    Pin one product to the top of search results for “running shoes”, for two weeks:

    Terminal window
    curl -X POST 'https://api.eu1.luigisbox.ai/platform/v1/campaigns' \
    -H 'Authorization: Bearer <token>' \
    -H 'Content-Type: application/json' \
    -d '{
    "organization_id": "lbo_r2vn8c",
    "name": "Spring running push",
    "status": "active",
    "starts_at": "2026-04-01T00:00:00Z",
    "ends_at": "2026-04-15T00:00:00Z",
    "catalog_ids": ["lbc_8w3k2p"],
    "intents": ["search"],
    "match": {
    "operator": "and",
    "conditions": [
    { "field": "trigger.request:query", "operator": "matches", "value": "running shoes" }
    ]
    },
    "rules": [
    {
    "name": "Hero: Kestrel Trail",
    "record_match": {
    "operator": "and",
    "conditions": [
    { "field": "@id", "operator": "eq", "value": "product/sku-4410" }
    ]
    },
    "effect": { "type": "pin", "position": 1 }
    }
    ]
    }'

    The response is 201 with the created campaign, its lbm_… ID and its rules’ lbr_… IDs.

    Read that body as the four questions in order: catalog_ids and intents are the targeting, match is the trigger, starts_at / ends_at are the schedule, and the one rule pairs a product selector with an effect. A pin holds for the whole campaign; a boost or bury can instead fade over a decay_window — see Rules and effects.

    A campaign carries two condition trees that look alike and answer different questions:

    TreeAsksFields
    match on the campaignDoes this campaign apply to this request?trigger.-prefixed
    record_match on a ruleWhich products does this rule act on?Catalog fields

    A rule only runs on requests its campaign fires on, and a campaign that fires but whose rules select no products does nothing. Both trees have to be right.

    statusBehaviour
    draftSaved, never served. The default.
    activeServed, subject to its schedule
    pausedSaved and not served; can be reactivated
    archivedTerminal

    starts_at and ends_at are UTC instants and are optional — leave both out for a campaign that runs whenever it is active. timezone records the zone the schedule was authored in so it can be reopened there; it is informational and never shifts the instants.

    • Give rules names that say why. "Supplier deal — Northwear Q2" explains itself six months later; "Boost 1" does not.
    • Prefer criteria to lists of IDs. A rule on clearance = true keeps working as stock turns over; a list of 200 IDs decays into a maintenance job.
    • Always set ends_at for a promotion. Campaigns that outlive their reason are the main cause of results nobody can explain.
    • Pick the right tool for hiding products. A ban hides a set of products in one context: prescription drugs in recommenders but not in search, or a category the mobile app does not sell. Target the campaign by intent or channel and leave ends_at out. Use a channel’s visibility filter when the products should never appear on that channel at all, and remove products from the catalog when they should appear nowhere.
    • Check the effect. A rule trades relevance for control. Watch the surface’s reporting after a campaign goes live — see Analytics.
    Rules and effectsWhich products, and what happens to them
    TriggersWhich requests a campaign fires on
    TargetingWhich catalogs, channels, surfaces and intents it covers
    Resolving conflictsWho wins when several rules hit one product
    Authoring APIThe endpoints, field by field