Create or replace an automatic promotion rule
UPSERTS one automatic promotion rule by id: there is no separate create and update, and no PATCH. Posting an existing id REPLACES that rule wholesale — every field not in your body is destroyed, including the reward mechanics. The read-modify-write path is GET /v1/promotions/{id}/rule (the directory reads carry no mechanics): read the live rule there, change the one field you were asked to change, and send the whole object back. If that read 404s (the promotion carries no configured rule) STOP and ask; do not reconstruct plausible values to satisfy the schema, as that silently overwrites a live pricing rule. Pick the type by the mechanic you want: bogo (buy buyQuantity of buySkuId, get getQuantity of getSkuId at getDiscountBps off — 10000 bps makes it free), threshold (once skuId reaches minQuantity units, a percent or flat reward comes off that SKU’s subtotal) or bundle (buy the components together and pay bundlePriceCents). Money is integer CENTS and percentages are BASIS POINTS (1000 = 10%). validFrom/validUntil are inclusive ISO-8601 instants (Z or a UTC offset) and validUntil must not precede validFrom. Use this for an always-on offer any matching basket earns; use POST /v1/coupons instead when the reduction must be unlocked by a code the customer presents.
Authorizations
Authorization: Bearer <token>. Accepts EITHER a Keycloak access token (scopes-in-token) OR an opaque POS session token; both resolve to the same pos.* scope vocabulary the route guards enforce.
Body
- Option 1
- Option 2
- Option 3
1^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$bogo ^[0-9a-f]{64}$0 < x <= 9007199254740991^[0-9a-f]{64}$0 < x <= 90071992547409911 <= x <= 10000Response
The persisted rule, echoed back with its validity window as ISO instants. The example shows a bogo rule; the threshold shape is on evaluatePromotions and the bundle shape on updatePromotion.
- Option 1
- Option 2
- Option 3
The persisted rule, echoed back with its validity window as ISO instants. The example shows a bogo rule; the threshold shape is on evaluatePromotions and the bundle shape on updatePromotion.
1^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$bogo ^[0-9a-f]{64}$0 < x <= 9007199254740991^[0-9a-f]{64}$0 < x <= 90071992547409911 <= x <= 10000
