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.

    Update a campaign

    View source
    PATCH
    /platform/v1/campaigns/{campaign_id}
    curl --request PATCH \
    --url 'https://api.eu1.luigisbox.ai/platform/v1/campaigns/example?filter_syntax=group' \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{ "catalog_ids": [ "example" ], "catalog_tags": [ "example" ], "channel_ids": [ "example" ], "channel_tags": [ "example" ], "ends_at": "2026-04-15T12:00:00Z", "intents": [ "search" ], "match": { "$and": [ { "brand": { "in": [ "nike", "adidas" ] } }, { "lbx:price": { "gte": 50, "lte": 200 } }, { "$or": [ { "condition": { "eq": "new" } }, { "warranty_months": { "gte": 12 } } ] }, { "$not": { "material": { "eq": "leather" } } }, { "image": { "exists": true } } ] }, "name": "example", "rules": [ { "effect": { "content_type": "product", "decay_window": "example", "disclosure_type": "sponsored", "mode": "hard", "position": 1, "respect_user_filters": false, "type": "pin" }, "id": "example", "name": "example", "record_match": { "$and": [ { "brand": { "in": [ "nike", "adidas" ] } }, { "lbx:price": { "gte": 50, "lte": 200 } }, { "$or": [ { "condition": { "eq": "new" } }, { "warranty_months": { "gte": 12 } } ] }, { "$not": { "material": { "eq": "leather" } } }, { "image": { "exists": true } } ] } } ], "starts_at": "2026-04-15T12:00:00Z", "status": "draft", "surface_ids": [ "example" ], "surface_tags": [ "example" ], "timezone": "example" }'

    Partial update. An archived campaign is terminal: every update is rejected with 409, including a status change, so it can never be un-archived — create a new campaign instead. A present rules list fully replaces the rule set.

    campaign_id
    required
    Campaign Id
    string
    filter_syntax
    FilterSyntax

    Syntax filter trees are rendered in. group is the {operator, conditions} form; map is the $and / $or / $not map syntax the Discovery API uses, in which an empty tree renders as null. Request bodies accept either syntax regardless of this setting.

    string
    default: group
    Allowed values: group map

    Syntax filter trees are rendered in. group is the {operator, conditions} form; map is the $and / $or / $not map syntax the Discovery API uses, in which an empty tree renders as null. Request bodies accept either syntax regardless of this setting.

    Media type application/json
    CampaignUpdate

    Partial update (JSON Merge Patch). Only fields present in the request are applied.

    A present rules list fully replaces the campaign’s rule set, within the bounds published on the field (a campaign is never left ruleless). Rules carrying an id keep that id (and their analytics history); id-less rules are created new.

    object
    catalog_ids
    Catalog Ids
    Array<string>
    catalog_tags
    Catalog Tags
    Array<string>
    channel_ids
    Channel Ids
    Array<string>
    channel_tags
    Channel Tags
    Array<string>
    ends_at
    Any of:
    string format: date-time
    intents
    Intents

    Surface Intents this campaign targets — the kind of discovery it applies to. Empty means every Intent, not none. Narrowing by Intent is mutually exclusive with narrowing by surface_ids / surface_tags: an Intent targets whole families of surfaces, so combining the two is rejected with intents_conflict. A targeted Intent no scoped catalog hosts a surface for is rejected with catalog_without_targeted_intent — it could never trigger.

    Array<string>
    Allowed values: search recommender collection
    match
    Any of:
    One of:
    FilterGroup

    A filter tree in group syntax: a boolean operator over leaves and nested groups.

    not holds exactly one child. An empty and constrains nothing and an empty or matches nothing; each endpoint says whether it accepts either.

    object
    conditions
    Conditions

    Leaf conditions and nested groups.

    Array
    One of:
    FilterCondition

    One leaf of a group-syntax tree: a field compared against a value.

    object
    field
    required
    Field

    Object field the condition reads.

    string
    on_missing
    Any of:
    DynamicFilterMissingPolicy

    What a condition reading its value from the request’s anchors does when none carries the attribute.

    fail_closed (the default) makes the whole filter tree match nothing. ignore drops the condition instead, leaving the rest of the tree in force.

    string
    Allowed values: fail_closed ignore
    operator
    required
    FilterOperator

    Comparison operator.

    string
    Allowed values: eq neq gt gte lt lte in not_in matches starts_with ends_with range exists
    source
    FilterSource

    Provenance of the condition; stamped by the system, never read from a client.

    string
    default: request
    Allowed values: request collection surface autofilter business_rule visibility
    value
    Value

    Literal to compare against, or a trigger reference {trigger_ref: ...}; a scalar for eq/neq and the comparisons, a non-empty list for in/not_in, absent for exists.

    value_from
    Any of:
    FilterValueFrom

    Where a dynamic condition reads its value: an attribute of the request’s anchors.

    object
    anchor_attribute
    required
    Anchor Attribute

    Anchor attribute whose value the condition compares against.

    string
    operator
    required
    BooleanOperator

    Boolean combinator applied to conditions.

    string
    Allowed values: and or not
    name
    Name
    string
    >= 1 characters <= 256 characters
    rules
    Any of:
    Array<object>
    >= 1 items <= 50 items
    RuleUpsert

    A rule in an update payload. An id echoed back from a prior response marks an existing rule to keep — its fields are updated in place and its rule_id (which analytics attribution aggregates on) is preserved. Omit id to create a new rule; existing rules absent from the list are dropped.

    object
    effect
    required
    One of: discriminator: type
    PinEffect

    Pin the selected product to a fixed 1-indexed position.

    mode='soft' is the Soft Pin: the placement decays over decay_window. content_type / disclosure_type / respect_user_filters are accepted and stored but have no effect on results.

    object
    content_type
    Any of:
    string
    Allowed values: product banner
    decay_window
    Any of:
    string format: duration
    disclosure_type
    Any of:
    string
    Allowed values: sponsored support
    mode
    Mode
    string
    default: hard
    Allowed values: hard soft
    position
    required
    Position
    integer
    > 0
    respect_user_filters
    Respect User Filters
    boolean
    type
    Type
    string
    default: pin
    Allowed value: pin
    id
    Any of:
    string
    name
    required
    Name
    string
    >= 1 characters <= 256 characters
    record_match
    required
    Any of:
    One of:
    FilterGroup

    A filter tree in group syntax: a boolean operator over leaves and nested groups.

    not holds exactly one child. An empty and constrains nothing and an empty or matches nothing; each endpoint says whether it accepts either.

    object
    conditions
    Conditions

    Leaf conditions and nested groups.

    Array
    One of:
    FilterCondition

    One leaf of a group-syntax tree: a field compared against a value.

    object
    field
    required
    Field

    Object field the condition reads.

    string
    on_missing
    Any of:
    DynamicFilterMissingPolicy

    What a condition reading its value from the request’s anchors does when none carries the attribute.

    fail_closed (the default) makes the whole filter tree match nothing. ignore drops the condition instead, leaving the rest of the tree in force.

    string
    Allowed values: fail_closed ignore
    operator
    required
    FilterOperator

    Comparison operator.

    string
    Allowed values: eq neq gt gte lt lte in not_in matches starts_with ends_with range exists
    source
    FilterSource

    Provenance of the condition; stamped by the system, never read from a client.

    string
    default: request
    Allowed values: request collection surface autofilter business_rule visibility
    value
    Value

    Literal to compare against, or a trigger reference {trigger_ref: ...}; a scalar for eq/neq and the comparisons, a non-empty list for in/not_in, absent for exists.

    value_from
    Any of:
    FilterValueFrom

    Where a dynamic condition reads its value: an attribute of the request’s anchors.

    object
    anchor_attribute
    required
    Anchor Attribute

    Anchor attribute whose value the condition compares against.

    string
    operator
    required
    BooleanOperator

    Boolean combinator applied to conditions.

    string
    Allowed values: and or not
    starts_at
    Any of:
    string format: date-time
    status
    CampaignStatus

    Lifecycle state of a Campaign.

    string
    Allowed values: draft active paused archived
    surface_ids
    Surface Ids
    Array<string>
    surface_tags
    Surface Tags
    Array<string>
    timezone
    Any of:
    string
    <= 64 characters

    Successful Response

    Media type application/json
    Campaign

    Campaign response: the explicit picks the merchandiser made, round-trippable into an update.

    The effective scope — those picks unioned with the current members of the picked tags — is not here; read it from GET /platform/v1/campaigns/{campaign_id}/effective-scope. See :class:CampaignEffectiveScope.

    object
    catalog_ids
    required
    Catalog Ids
    Array<string>
    catalog_tags
    required
    Catalog Tags
    Array<string>
    channel_ids
    required
    Channel Ids
    Array<string>
    channel_tags
    required
    Channel Tags
    Array<string>
    created_at
    required
    Created At
    string format: date-time
    created_by
    required
    Any of:
    string
    ends_at
    required
    Any of:
    string format: date-time
    id
    required
    Id
    string
    intents
    required
    Intents

    Surface Intents this campaign targets — the kind of discovery it applies to. Empty means every Intent, not none. Narrowing by Intent is mutually exclusive with narrowing by surface_ids / surface_tags: an Intent targets whole families of surfaces, so combining the two is rejected with intents_conflict. A targeted Intent no scoped catalog hosts a surface for is rejected with catalog_without_targeted_intent — it could never trigger.

    Array<string>
    Allowed values: search recommender collection
    match
    required
    Any of:
    FilterGroup

    A filter tree in group syntax: a boolean operator over leaves and nested groups.

    not holds exactly one child. An empty and constrains nothing and an empty or matches nothing; each endpoint says whether it accepts either.

    object
    conditions
    Conditions

    Leaf conditions and nested groups.

    Array
    One of:
    FilterCondition

    One leaf of a group-syntax tree: a field compared against a value.

    object
    field
    required
    Field

    Object field the condition reads.

    string
    on_missing
    Any of:
    DynamicFilterMissingPolicy

    What a condition reading its value from the request’s anchors does when none carries the attribute.

    fail_closed (the default) makes the whole filter tree match nothing. ignore drops the condition instead, leaving the rest of the tree in force.

    string
    Allowed values: fail_closed ignore
    operator
    required
    FilterOperator

    Comparison operator.

    string
    Allowed values: eq neq gt gte lt lte in not_in matches starts_with ends_with range exists
    source
    FilterSource

    Provenance of the condition; stamped by the system, never read from a client.

    string
    default: request
    Allowed values: request collection surface autofilter business_rule visibility
    value
    Value

    Literal to compare against, or a trigger reference {trigger_ref: ...}; a scalar for eq/neq and the comparisons, a non-empty list for in/not_in, absent for exists.

    value_from
    Any of:
    FilterValueFrom

    Where a dynamic condition reads its value: an attribute of the request’s anchors.

    object
    anchor_attribute
    required
    Anchor Attribute

    Anchor attribute whose value the condition compares against.

    string
    operator
    required
    BooleanOperator

    Boolean combinator applied to conditions.

    string
    Allowed values: and or not
    name
    required
    Name
    string
    organization_id
    required
    Organization Id
    string
    rules
    Rules
    Array<object>
    Rule
    object
    campaign_id
    required
    Campaign Id
    string
    created_at
    required
    Created At
    string format: date-time
    created_by
    required
    Any of:
    string
    effect
    required
    One of: discriminator: type
    PinEffect

    Pin the selected product to a fixed 1-indexed position.

    mode='soft' is the Soft Pin: the placement decays over decay_window. content_type / disclosure_type / respect_user_filters are accepted and stored but have no effect on results.

    object
    content_type
    Any of:
    string
    Allowed values: product banner
    decay_window
    Any of:
    string format: duration
    disclosure_type
    Any of:
    string
    Allowed values: sponsored support
    mode
    Mode
    string
    default: hard
    Allowed values: hard soft
    position
    required
    Position
    integer
    > 0
    respect_user_filters
    Respect User Filters
    boolean
    type
    Type
    string
    default: pin
    Allowed value: pin
    id
    required
    Id
    string
    name
    required
    Name
    string
    record_match
    required
    Any of:
    FilterGroup

    A filter tree in group syntax: a boolean operator over leaves and nested groups.

    not holds exactly one child. An empty and constrains nothing and an empty or matches nothing; each endpoint says whether it accepts either.

    object
    conditions
    Conditions

    Leaf conditions and nested groups.

    Array
    One of:
    FilterCondition

    One leaf of a group-syntax tree: a field compared against a value.

    object
    field
    required
    Field

    Object field the condition reads.

    string
    on_missing
    Any of:
    DynamicFilterMissingPolicy

    What a condition reading its value from the request’s anchors does when none carries the attribute.

    fail_closed (the default) makes the whole filter tree match nothing. ignore drops the condition instead, leaving the rest of the tree in force.

    string
    Allowed values: fail_closed ignore
    operator
    required
    FilterOperator

    Comparison operator.

    string
    Allowed values: eq neq gt gte lt lte in not_in matches starts_with ends_with range exists
    source
    FilterSource

    Provenance of the condition; stamped by the system, never read from a client.

    string
    default: request
    Allowed values: request collection surface autofilter business_rule visibility
    value
    Value

    Literal to compare against, or a trigger reference {trigger_ref: ...}; a scalar for eq/neq and the comparisons, a non-empty list for in/not_in, absent for exists.

    value_from
    Any of:
    FilterValueFrom

    Where a dynamic condition reads its value: an attribute of the request’s anchors.

    object
    anchor_attribute
    required
    Anchor Attribute

    Anchor attribute whose value the condition compares against.

    string
    operator
    required
    BooleanOperator

    Boolean combinator applied to conditions.

    string
    Allowed values: and or not
    updated_at
    required
    Updated At
    string format: date-time
    updated_by
    required
    Any of:
    string
    starts_at
    required
    Any of:
    string format: date-time
    status
    required
    CampaignStatus

    Lifecycle state of a Campaign.

    string
    Allowed values: draft active paused archived
    surface_ids
    required
    Surface Ids
    Array<string>
    surface_tags
    required
    Surface Tags
    Array<string>
    timezone
    Timezone

    IANA timezone identifier (e.g. Europe/Bratislava) the schedule was authored in, kept so it can be re-opened in that zone. Informational only: starts_at / ends_at are the UTC instants that govern when the campaign runs, and this field never shifts them — use it when re-planning a schedule, never to compute execution times. Requires at least one of starts_at / ends_at, and is cleared when both are cleared. Because tz databases differ between releases and between server and browser (Europe/Kiev vs Europe/Kyiv), a client whose own database does not know the identifier should keep the string as it is rather than discard or rewrite it. A scheduled campaign always reads back a zone — UTC when none was authored; an unscheduled one omits the field, so a response never shows the zone-without-schedule state that writes reject.

    string
    default: UTC <= 64 characters
    updated_at
    required
    Updated At
    string format: date-time
    updated_by
    required
    Any of:
    string
    Example
    {
    "intents": [
    "search"
    ],
    "match": {
    "$and": [
    {
    "brand": {
    "in": [
    "nike",
    "adidas"
    ]
    }
    },
    {
    "lbx:price": {
    "gte": 50,
    "lte": 200
    }
    },
    {
    "$or": [
    {
    "condition": {
    "eq": "new"
    }
    },
    {
    "warranty_months": {
    "gte": 12
    }
    }
    ]
    },
    {
    "$not": {
    "material": {
    "eq": "leather"
    }
    }
    },
    {
    "image": {
    "exists": true
    }
    }
    ]
    },
    "rules": [
    {
    "effect": {
    "content_type": "product",
    "disclosure_type": "sponsored",
    "mode": "hard",
    "respect_user_filters": false,
    "type": "pin"
    },
    "record_match": {
    "$and": [
    {
    "brand": {
    "in": [
    "nike",
    "adidas"
    ]
    }
    },
    {
    "lbx:price": {
    "gte": 50,
    "lte": 200
    }
    },
    {
    "$or": [
    {
    "condition": {
    "eq": "new"
    }
    },
    {
    "warranty_months": {
    "gte": 12
    }
    }
    ]
    },
    {
    "$not": {
    "material": {
    "eq": "leather"
    }
    }
    },
    {
    "image": {
    "exists": true
    }
    }
    ]
    }
    }
    ],
    "status": "draft",
    "timezone": "UTC"
    }

    Missing or invalid credentials

    Media type application/json
    ErrorResponse

    Canonical error body — every non-2xx response uses this shape.

    object
    exception_details
    ExceptionDetails

    Machine-readable error context; empty object when there is nothing to add.

    object
    validation_errors
    Any of:
    Array<object>
    ValidationProblem

    One field-level reason a request was rejected.

    object
    loc
    required
    Loc

    Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].

    Array
    msg
    required
    Msg

    What is wrong with the value at loc.

    string
    type
    required
    Type

    Stable machine code for the problem, e.g. missing or string_too_short.

    string
    key
    additional properties
    any
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example generated
    {
    "exception_details": {
    "validation_errors": [
    {
    "loc": [
    "example"
    ],
    "msg": "example",
    "type": "example"
    }
    ]
    },
    "reason": "example",
    "request_id": "example"
    }

    Authenticated but not permitted

    Media type application/json
    ErrorResponse

    Canonical error body — every non-2xx response uses this shape.

    object
    exception_details
    ExceptionDetails

    Machine-readable error context; empty object when there is nothing to add.

    object
    validation_errors
    Any of:
    Array<object>
    ValidationProblem

    One field-level reason a request was rejected.

    object
    loc
    required
    Loc

    Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].

    Array
    msg
    required
    Msg

    What is wrong with the value at loc.

    string
    type
    required
    Type

    Stable machine code for the problem, e.g. missing or string_too_short.

    string
    key
    additional properties
    any
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example generated
    {
    "exception_details": {
    "validation_errors": [
    {
    "loc": [
    "example"
    ],
    "msg": "example",
    "type": "example"
    }
    ]
    },
    "reason": "example",
    "request_id": "example"
    }

    Resource not found

    Media type application/json
    ErrorResponse

    Canonical error body — every non-2xx response uses this shape.

    object
    exception_details
    ExceptionDetails

    Machine-readable error context; empty object when there is nothing to add.

    object
    validation_errors
    Any of:
    Array<object>
    ValidationProblem

    One field-level reason a request was rejected.

    object
    loc
    required
    Loc

    Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].

    Array
    msg
    required
    Msg

    What is wrong with the value at loc.

    string
    type
    required
    Type

    Stable machine code for the problem, e.g. missing or string_too_short.

    string
    key
    additional properties
    any
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example generated
    {
    "exception_details": {
    "validation_errors": [
    {
    "loc": [
    "example"
    ],
    "msg": "example",
    "type": "example"
    }
    ]
    },
    "reason": "example",
    "request_id": "example"
    }

    State conflict: the campaign is archived (terminal — every update is rejected, including a status change), or the requested name is already used by another campaign in the organization.

    Media type application/json
    ErrorResponse

    Canonical error body — every non-2xx response uses this shape.

    object
    exception_details
    ExceptionDetails

    Machine-readable error context; empty object when there is nothing to add.

    object
    validation_errors
    Any of:
    Array<object>
    ValidationProblem

    One field-level reason a request was rejected.

    object
    loc
    required
    Loc

    Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].

    Array
    msg
    required
    Msg

    What is wrong with the value at loc.

    string
    type
    required
    Type

    Stable machine code for the problem, e.g. missing or string_too_short.

    string
    key
    additional properties
    any
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example generated
    {
    "exception_details": {
    "validation_errors": [
    {
    "loc": [
    "example"
    ],
    "msg": "example",
    "type": "example"
    }
    ]
    },
    "reason": "example",
    "request_id": "example"
    }

    Request validation failed. A targeting rejection lists every problem at once in exception_details.problems.

    Media type application/json
    Any of:
    TargetingProblemsError

    The canonical error body of a rejected targeting set, with problems typed.

    reason and request_id are the canonical fields; exception_details carries the typed problems list.

    object
    exception_details
    required
    TargetingProblems

    The exception_details of a rejected targeting set: every problem found at once.

    object
    problems
    required
    Problems

    Every targeting violation found in one pass; never truncated.

    Array<object>
    TargetingProblem

    One targeting violation: a stable machine code plus the offending values.

    object
    code
    required
    TargetingProblemCode

    Stable machine code of the violated rule.

    string
    Allowed values: catalog_scope_required intents_conflict catalog_not_in_organization channel_not_in_organization tag_not_found tag_dimension_mismatch surface_not_in_catalog_scope catalog_without_targeted_surface channel_outside_catalog_scope catalog_without_targeted_intent
    dimension
    required
    Dimension

    The targeting axis the violation is about.

    string
    Allowed values: catalog channel surface intent
    message
    required
    Message

    Human-readable explanation of the violation.

    string
    values
    required
    Values

    The offending values on that axis.

    Array<string>
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example
    {
    "exception_details": {
    "problems": [
    {
    "code": "catalog_scope_required",
    "dimension": "catalog"
    }
    ]
    }
    }

    The catalog’s attribute types could not be read, so the request could not be type-checked; retryable.

    Media type application/json
    ErrorResponse

    Canonical error body — every non-2xx response uses this shape.

    object
    exception_details
    ExceptionDetails

    Machine-readable error context; empty object when there is nothing to add.

    object
    validation_errors
    Any of:
    Array<object>
    ValidationProblem

    One field-level reason a request was rejected.

    object
    loc
    required
    Loc

    Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].

    Array
    msg
    required
    Msg

    What is wrong with the value at loc.

    string
    type
    required
    Type

    Stable machine code for the problem, e.g. missing or string_too_short.

    string
    key
    additional properties
    any
    reason
    required
    Reason

    Human-readable, actionable error message.

    string
    request_id
    Any of:
    string
    Example generated
    {
    "exception_details": {
    "validation_errors": [
    {
    "loc": [
    "example"
    ],
    "msg": "example",
    "type": "example"
    }
    ]
    },
    "reason": "example",
    "request_id": "example"
    }