Getting Started with Promotions
Welcome to the final guide in the series. You've built a catalog, priced it, and taxed it — now let's make it sing with promotions. This guide walks you through creating and managing Promotions on the Hii Retail platform using the Promotion Management API v3. By the end, you'll understand how a promotion is structured, the difference between central and local promotions, and how to create, query, update, and delete them.
Hii Retail has two generations of promotion APIs. The original Promotion Input API / Promotion Query API carry promotions as an XML string for compatibility with legacy POS systems. The Promotion Management API v3 covered in this guide is a fully structured JSON API that replaces them, and is the way to integrate going forward. Build against v3 for all new integrations.
Overview
What is a Promotion?
A Promotion is a rule that reduces the price the customer pays — a campaign price, a percentage off a category, a "buy 2 for the price of 1" bundle, a loyalty-member discount, and so on. You define promotions through the Management API; the Promotion Engine then evaluates them against each basket at the point of sale and returns the calculated discounts to the POS.
You describe what the promotion should do. The engine decides how and when it applies.
┌──────────────────────────────────────────────────────────────────┐
│ Promotion │
│ id · validFrom/validTo · status · conflictResolutionType │
├──────────────────────────────────────────────────────────────────┤
│ │
│ Activators (optional gate — must pass before offers evaluate) │
│ e.g. loyalty, coupon, staff, channel, B2B │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Offer │ │
│ │ Conditions (what must be in the basket) │ │
│ │ e.g. item set "soft drinks", min quantity 2 │ │
│ │ Reward (what the customer gets) │ │
│ │ e.g. 20% off the matched items │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ …or a simpler campaignPrices list: a flat new price per item │
│ │
└──────────────────────────────────────────────────────────────────┘
Key building blocks
| Concept | Description |
|---|---|
| Activator | An optional gate that must be satisfied before any offers are evaluated — loyalty membership, a coupon code, a staff transaction, a sales channel, or a B2B customer. Multiple activators are combined with logical AND. |
| Offer | A condition–reward pair. A promotion can hold several offers. |
| Condition | What must be present in the basket — an item set (matched by category, item ID, brand, etc.) with optional minQuantity/minAmount, or a totalAmount threshold. |
| Reward | What the customer gets — a reduced percent or amount, a discounted/package price, or a total-basket discount. |
| Campaign price | A simpler alternative to offers: a flat new unit price for specific items, with no conditions to evaluate. |
| conflictResolutionType | Determines how this promotion competes with others when several match the same items (see below). |
Central vs local promotions
The API exposes three resources. Which one you use depends on who owns the promotion and how its scope is determined.
Promotion Management API v3
┌───────────────────────────┬───────────────────────────────────────┐
│ /promotions │ Central promotions │
│ │ Scope set in the body: │
│ │ businessUnitId OR businessUnitGroupId│
├───────────────────────────┼───────────────────────────────────────┤
│ /local-promotions │ Store-owned promotions │
│ /local-campaigns │ Scope (business unit) is taken from │
│ │ the access token, not the body │
└───────────────────────────┴───────────────────────────────────────┘
- Central promotions (
/promotions) target either a single business unit (businessUnitId) or a whole business unit group (businessUnitGroupId), set in the request body. A central promotion manager may manage any promotion in the tenant. - Local promotions and campaigns (
/local-promotions,/local-campaigns) apply only to the caller's own store. The business unit is taken authoritatively from the token, never from the body — a store manager can only ever change their own store's promotions.
This guide focuses on central promotions; the local endpoints behave identically except for where the business unit comes from.
Conflict resolution
When more than one promotion matches the same items, the conflictResolutionType decides which wins. The set of types is configurable per tenant, and each type has a defined relationship to every other type. Common types include:
| Type | Typical use |
|---|---|
CAMPAIGN | Campaign prices |
SALE | Standard sale offers |
MIXMATCH | Multi-buy / bundle deals |
TOTAL_DISCOUNT | Basket-total discounts |
STAFF | Staff discounts |
B2B | Negotiated B2B agreement prices |
Two promotions sharing the same conflictResolutionType always resolve with the Best Deal strategy — the engine applies whichever gives the customer the lower price. You can override the default relationship between different types through Customer Controlled Configuration — see Promotion Configuration at the end of this guide.
Prerequisites
Before you begin, ensure you have:
- Business Units created: At least one Business Unit or Business Unit Group to scope promotions to (see Business Units guide)
- Items and prices: The items your promotions target should already exist with an active sales price (Items guide, Prices guide)
- Authentication token: A valid JWT bearer token whose client holds the appropriate Promotion Engine role (see Authentication below)
API Base URL
All Promotion Management API requests are sent to:
https://promotion-api.retailsvc.com/api/v3
The full, interactive endpoint reference is published at Promotion Management API v3.
Authentication
Every request must carry a JWT bearer token in the Authorization header:
Roles and permissions
Access is role-based. Rather than granting individual permissions, you assign one of the predefined Promotion Engine roles to your OCMS client (or to IAM users, for interactive access). Each role carries the permissions the API checks per operation:
| Role | Grants | Scope |
|---|---|---|
promotion-admin | Create, update, delete, and query — across central promotions, local promotions, and local campaigns | Everything |
promotion-create | pro.promotion.create | Create/update central promotions |
promotion-view | pro.promotion.query | Read central promotions |
local-promotion-admin | All pro.local-promotion.* | Manage local promotions |
local-promotion-create / local-promotion-view | Create/update or read | Local promotions |
local-campaign-admin | All pro.local-campaign.* | Manage local campaigns |
local-campaign-create / local-campaign-view | Create/update or read | Local campaigns |
For a back-office integration that manages everything, promotion-admin is the usual choice. The create permission covers both creating and updating a promotion.
Step 1: Create a Campaign Price
The simplest promotion: a flat new price for specific items during a campaign window. No conditions to evaluate. This example runs a summer campaign that drops Fanta Orange from €14.99 to €11.99 across the whole Business Unit Group, so it propagates to every store in the group.
Permission:
pro.promotion.create(rolepromotion-createorpromotion-admin).
Required fields
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for this promotion (max 250 characters) |
revision | integer | Version of the entity. Use an epoch timestamp in milliseconds. A later write must use a higher value or it is ignored as outdated. |
conflictResolutionType | string | How this promotion competes with others (e.g. CAMPAIGN) |
status | string | ACTIVE or DELETED |
name | string | Display name shown in frontend applications |
validFrom | datetime | When the promotion becomes effective (ISO 8601). Time defaults to 00:00:00.000. |
businessUnitGroupId or businessUnitId | string | The scope of the promotion |
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://promotion-api.retailsvc.com/api/v3/promotions' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "SUMMER-CAMPAIGN-2026",
"revision": 1780272000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "CAMPAIGN",
"status": "ACTIVE",
"name": "Summer Campaign",
"receiptText": "Summer Sale",
"validFrom": "2026-06-01T00:00:00Z",
"validTo": "2026-08-31T23:59:59Z",
"campaignPrices": [
{ "itemId": "5449000051578", "unitPrice": 11.99 }
]
}'
response = requests.post(
"https://promotion-api.retailsvc.com/api/v3/promotions",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "SUMMER-CAMPAIGN-2026",
"revision": 1748736000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "CAMPAIGN",
"status": "ACTIVE",
"name": "Summer Campaign",
"receiptText": "Summer Sale",
"validFrom": "2026-06-01T00:00:00Z",
"validTo": "2026-08-31T23:59:59Z",
"campaignPrices": [
{"itemId": "5449000051578", "unitPrice": 11.99}
]
}
)
const response = await fetch('https://promotion-api.retailsvc.com/api/v3/promotions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'SUMMER-CAMPAIGN-2026',
revision: 1748736000000,
businessUnitGroupId: 'acme-retail-group',
conflictResolutionType: 'CAMPAIGN',
status: 'ACTIVE',
name: 'Summer Campaign',
receiptText: 'Summer Sale',
validFrom: '2026-06-01T00:00:00Z',
validTo: '2026-08-31T23:59:59Z',
campaignPrices: [
{ itemId: '5449000051578', unitPrice: 11.99 }
]
})
});
var payload = """
{
"id": "SUMMER-CAMPAIGN-2026",
"revision": 1748736000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "CAMPAIGN",
"status": "ACTIVE",
"name": "Summer Campaign",
"receiptText": "Summer Sale",
"validFrom": "2026-06-01T00:00:00Z",
"validTo": "2026-08-31T23:59:59Z",
"campaignPrices": [
{ "itemId": "5449000051578", "unitPrice": 11.99 }
]
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://promotion-api.retailsvc.com/api/v3/promotions"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "SUMMER-CAMPAIGN-2026",
revision = 1748736000000L,
businessUnitGroupId = "acme-retail-group",
conflictResolutionType = "CAMPAIGN",
status = "ACTIVE",
name = "Summer Campaign",
receiptText = "Summer Sale",
validFrom = "2026-06-01T00:00:00Z",
validTo = "2026-08-31T23:59:59Z",
campaignPrices = new[] {
new { itemId = "5449000051578", unitPrice = 11.99 }
}
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://promotion-api.retailsvc.com/api/v3/promotions", content);
Response
A successful request returns 202 Accepted.
The Promotion Management API processes requests asynchronously. A 202 Accepted response means your promotion has been queued for processing — it is not instantly queryable or active at the till. Build for eventual consistency, and confirm the result by reading the promotion back (see Step 5) rather than assuming it is live on the next call.
Step 2: Create an Offer-Based Promotion
Most promotions go beyond a flat price. An offer pairs a condition (what must be in the basket) with a reward (what the customer gets). This example gives 20% off every item in the beverages-soft-drinks category.
Permission:
pro.promotion.create(rolepromotion-createorpromotion-admin).
Anatomy of an offer
| Element | Field path | Description |
|---|---|---|
| Offer | offers[] | A condition–reward pair. A promotion may hold several. |
| Item set | offers[].conditions[].itemSet.itemSetId | A named set of matched items. The reward refers back to it. |
| Filter | offers[].conditions[].itemSet.filters[] | What goes in the set — itemCategories, itemIds, brands, colors, sizes, seasons, modelIds, … |
| Quantity / amount gate | offers[].conditions[].itemSet.minQuantity / minAmount | Optional threshold the set must reach before the offer triggers |
| Reward | offers[].reward | What the customer gets — e.g. reducedPercent, reducedAmount, discountedPrice |
| Reward target | offers[].reward.*.targetItemSets[] | Which item set(s) the reward applies to, by itemSetId |
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://promotion-api.retailsvc.com/api/v3/promotions' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "SOFT-DRINKS-WEEK-2026",
"revision": 1748736000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "SALE",
"status": "ACTIVE",
"name": "Soft Drinks Week - 20% off",
"receiptText": "Soft Drinks -20%",
"validFrom": "2026-06-10T00:00:00Z",
"validTo": "2026-06-16T23:59:59Z",
"offers": [
{
"id": "offer-soft-drinks-20",
"conditions": [
{
"itemSet": {
"itemSetId": "SET-SOFT-DRINKS",
"filters": [
{ "itemCategories": ["beverages-soft-drinks"] }
]
}
}
],
"reward": {
"reducedPercent": {
"percent": 20.0,
"targetItemSets": ["SET-SOFT-DRINKS"]
}
}
}
]
}'
response = requests.post(
"https://promotion-api.retailsvc.com/api/v3/promotions",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "SOFT-DRINKS-WEEK-2026",
"revision": 1748736000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "SALE",
"status": "ACTIVE",
"name": "Soft Drinks Week - 20% off",
"receiptText": "Soft Drinks -20%",
"validFrom": "2026-06-10T00:00:00Z",
"validTo": "2026-06-16T23:59:59Z",
"offers": [
{
"id": "offer-soft-drinks-20",
"conditions": [
{
"itemSet": {
"itemSetId": "SET-SOFT-DRINKS",
"filters": [{"itemCategories": ["beverages-soft-drinks"]}]
}
}
],
"reward": {
"reducedPercent": {
"percent": 20.0,
"targetItemSets": ["SET-SOFT-DRINKS"]
}
}
}
]
}
)
const response = await fetch('https://promotion-api.retailsvc.com/api/v3/promotions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'SOFT-DRINKS-WEEK-2026',
revision: 1748736000000,
businessUnitGroupId: 'acme-retail-group',
conflictResolutionType: 'SALE',
status: 'ACTIVE',
name: 'Soft Drinks Week - 20% off',
receiptText: 'Soft Drinks -20%',
validFrom: '2026-06-10T00:00:00Z',
validTo: '2026-06-16T23:59:59Z',
offers: [
{
id: 'offer-soft-drinks-20',
conditions: [
{ itemSet: { itemSetId: 'SET-SOFT-DRINKS', filters: [{ itemCategories: ['beverages-soft-drinks'] }] } }
],
reward: { reducedPercent: { percent: 20.0, targetItemSets: ['SET-SOFT-DRINKS'] } }
}
]
})
});
var payload = """
{
"id": "SOFT-DRINKS-WEEK-2026",
"revision": 1748736000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "SALE",
"status": "ACTIVE",
"name": "Soft Drinks Week - 20% off",
"receiptText": "Soft Drinks -20%",
"validFrom": "2026-06-10T00:00:00Z",
"validTo": "2026-06-16T23:59:59Z",
"offers": [
{
"id": "offer-soft-drinks-20",
"conditions": [
{ "itemSet": { "itemSetId": "SET-SOFT-DRINKS",
"filters": [ { "itemCategories": ["beverages-soft-drinks"] } ] } }
],
"reward": { "reducedPercent": { "percent": 20.0, "targetItemSets": ["SET-SOFT-DRINKS"] } }
}
]
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://promotion-api.retailsvc.com/api/v3/promotions"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "SOFT-DRINKS-WEEK-2026",
revision = 1748736000000L,
businessUnitGroupId = "acme-retail-group",
conflictResolutionType = "SALE",
status = "ACTIVE",
name = "Soft Drinks Week - 20% off",
receiptText = "Soft Drinks -20%",
validFrom = "2026-06-10T00:00:00Z",
validTo = "2026-06-16T23:59:59Z",
offers = new[] {
new {
id = "offer-soft-drinks-20",
conditions = new[] {
new { itemSet = new {
itemSetId = "SET-SOFT-DRINKS",
filters = new[] { new { itemCategories = new[] { "beverages-soft-drinks" } } }
} }
},
reward = new { reducedPercent = new { percent = 20.0, targetItemSets = new[] { "SET-SOFT-DRINKS" } } }
}
}
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://promotion-api.retailsvc.com/api/v3/promotions", content);
Combine multiple conditions within an offer to require several item sets at once (e.g. "5 bags of cement AND 1 mixer"), and use minQuantity/minAmount to gate on quantity or spend. See the Promotion Management API reference for the full filter and reward catalogue.
Steps 1 and 2 show the full request in all five languages. The remaining operations differ only by URL and payload, so they're shown as cURL — translate them with the same client setup you used above.
Step 3: Create a Local Promotion
Local promotions apply only to the store that owns them. The request body is the same shape as a central promotion, but you send it to /local-promotions and you omit businessUnitId/businessUnitGroupId — the business unit is taken from the access token.
Permission:
pro.local-promotion.create(rolelocal-promotion-create,local-promotion-admin, orpromotion-admin). The store the promotion applies to is the one in your token.
curl -X POST 'https://promotion-api.retailsvc.com/api/v3/local-promotions' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "STORE-WEEKEND-SOFT-DRINKS",
"revision": 1748736000000,
"conflictResolutionType": "SALE",
"status": "ACTIVE",
"name": "Weekend 10% off soft drinks",
"validFrom": "2026-06-13T00:00:00Z",
"validTo": "2026-06-14T23:59:59Z",
"offers": [
{
"id": "offer-weekend-10",
"conditions": [
{ "itemSet": { "itemSetId": "SET-SOFT-DRINKS", "filters": [{ "itemCategories": ["beverages-soft-drinks"] }] } }
],
"reward": { "reducedPercent": { "percent": 10.0, "targetItemSets": ["SET-SOFT-DRINKS"] } }
}
]
}'
Local campaign prices work the same way — send a campaignPrices payload to /local-campaigns. The store scope still comes from the token.
Step 4: List and Query Promotions
GET /promotions returns promotions for the tenant. Use the filter query parameter to narrow the result with an RSQL expression. Combine predicates with ; (AND) and , (OR), and group with parentheses.
Permission:
pro.promotion.query(rolepromotion-vieworpromotion-admin).
# All active promotions in a group that are valid from June 2026 onwards
curl -G 'https://promotion-api.retailsvc.com/api/v3/promotions' \
-H 'Authorization: Bearer <your-access-token>' \
--data-urlencode 'filter=status==ACTIVE;businessUnitGroupId==acme-retail-group;validFrom=ge=2026-06-01T00:00:00Z' \
--data-urlencode 'limit=200'
Common searchable fields include id, name, reportingId, businessUnitId, businessUnitGroupId, validFrom, validTo, status, and conflictResolutionType. See the API reference for the full list of fields and operators.
Response and pagination
The response wraps the results in a metadata object plus an items array:
{
"metadata": {
"nextCursor": "eyJpZCI6IlNVTU1FUi1DQU1QQUlHTi0yMDI2In0",
"hasNextPage": true
},
"items": [
{ "id": "SUMMER-CAMPAIGN-2026", "status": "ACTIVE", "...": "..." },
{ "id": "SOFT-DRINKS-WEEK-2026", "status": "ACTIVE", "...": "..." }
]
}
Results are paged. limit defaults to 200 and cannot exceed 200. When metadata.hasNextPage is true, pass metadata.nextCursor back as the cursor parameter to fetch the next page, and repeat until hasNextPage is false:
curl -G 'https://promotion-api.retailsvc.com/api/v3/promotions' \
-H 'Authorization: Bearer <your-access-token>' \
--data-urlencode 'filter=status==ACTIVE;businessUnitGroupId==acme-retail-group' \
--data-urlencode 'cursor=eyJpZCI6IlNVTU1FUi1DQU1QQUlHTi0yMDI2In0'
If you only read the first response you'll silently miss everything beyond the 200-item limit. Always loop on hasNextPage when you expect more than a couple of hundred promotions.
Step 5: Verify and Fetch a Promotion
Because writes are asynchronous, reading a promotion back by its id is how you confirm processing succeeded — there is no push notification when a promotion finishes (or fails) processing. After a create or update, poll this endpoint until the promotion appears with the expected revision and status.
Permission:
pro.promotion.query(rolepromotion-vieworpromotion-admin).
curl 'https://promotion-api.retailsvc.com/api/v3/promotions/SUMMER-CAMPAIGN-2026' \
-H 'Authorization: Bearer <your-access-token>'
A 200 OK with the promotion body confirms it landed; a 404 Not Found means it either hasn't finished processing yet or was rejected — wait briefly and retry, and double-check the payload if it never appears.
Step 6: Update a Promotion
There is no separate update endpoint. To change a promotion, POST the same id again with a higher revision — the API performs an upsert and the newer revision replaces the older one. A write whose revision is lower than the stored value is treated as outdated and ignored.
Permission:
pro.promotion.create(rolepromotion-createorpromotion-admin).
curl -X POST 'https://promotion-api.retailsvc.com/api/v3/promotions' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "SUMMER-CAMPAIGN-2026",
"revision": 1782864000000,
"businessUnitGroupId": "acme-retail-group",
"conflictResolutionType": "CAMPAIGN",
"status": "ACTIVE",
"name": "Summer Campaign (extended)",
"validFrom": "2026-06-01T00:00:00Z",
"validTo": "2026-09-15T23:59:59Z",
"campaignPrices": [
{ "itemId": "5449000051578", "unitPrice": 10.99 }
]
}'
revisionIf you set revision to the current time in epoch milliseconds on every write, you get correct ordering for free — each update is naturally higher than the last. If you omit revision, Hii Retail assigns one for you, but providing it yourself gives you deterministic versioning. (Note 1782864000000 above is later than the 1780272000000 used at create time.)
Step 7: Delete a Promotion
Delete a promotion by its id:
Permission:
pro.promotion.delete(rolepromotion-admin).
curl -X DELETE 'https://promotion-api.retailsvc.com/api/v3/promotions/SUMMER-CAMPAIGN-2026' \
-H 'Authorization: Bearer <your-access-token>'
Like create and update, deletion is asynchronous: the call returns 202 Accepted to confirm the request was queued, and the promotion stops applying once processing completes. Read it back (Step 5) to confirm it's gone.
Promotion Configuration
Beyond individual promotions, you can tune how the engine resolves conflicts between conflict-resolution types for your tenant. This is done through Customer Controlled Configuration using the configuration kind pro.configuration.v1.
The configuration describes the relationships between conflict resolution types, letting you override the default Best Deal behaviour for a pair of conflicting promotions with:
LEFT_BEFORE_RIGHT— apply the left type first, then the rightLEFT_DISQUALIFIES_RIGHT— if the left type applies, the right is not applied at all
"Left" and "right" refer to the conflict resolution types named in the promotion definitions. The JSON schema is published in the Hii Retail JSON Schema Registry. For how to submit customer-controlled configuration, see the Customer Controlled Configuration documentation.
Testing
You have a test tenant alongside your production tenant. The test environment lives on the retailsvc-test.com domains — this is consistent across all Hii Retail services. To test, swap the hosts:
| Production | Test | |
|---|---|---|
| Token endpoint | https://auth.retailsvc.com/oauth2/token | https://auth.retailsvc-test.com/oauth2/token |
| Management API | https://promotion-api.retailsvc.com/api/v3 | https://promotion-api.retailsvc-test.com/api/v3 |
Next Steps
Now that you can manage promotions, you can:
- Add activators: Gate promotions behind loyalty membership, coupons, staff transactions, or sales channels
- Build multi-buy deals: Use multiple conditions and
quantityLimitto create bundles and "buy X get Y" offers - Tune conflict resolution: Submit a
pro.configuration.v1configuration to control how overlapping promotions interact - Automate: Sync promotions from your campaign-planning or ERP system into the Management API
Related Resources
- Promotion Management API v3 Reference
- Promotion Configuration schema (
pro.configuration.v1) - Customer Controlled Configuration
- OAuth2 Authentication
- Prices Guide
- Business Units Guide
Done! You've completed the Getting Started series. From here, explore the Promotion Management API v3 Reference for the full set of reward types, activators, and item filters.