| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Use this API to create and configure loyalty promotions. This allows you to manage a single promotion for multiple reward outcomes—such as loyalty points, coupons, badges, or tier upgrades.
What this API supports
- Creation of activity-based, generic, or broadcast promotions
- Customer enrollment rules (automatic via transactions, list imports, or audience segments)
- Configuration of simple (
SINGLE) or complex (GROUP) activities with specific triggers, event rules, and milestones - Definition of granular usage limits, point caps, and evaluation time windows (e.g., daily, weekly, or fixed calendar periods)
- Dynamic customer opt-in workflows and enrollment restrictions
- Liability splitting to distribute reward costs across programs or partners
Limits and configuration
- Using opt-in duration fields requires the
CONF_ENROLMENT_OPTIN_DURATION_ENABLEDorganisation flag to be enabled and is only supported forLOYALTY_EARNINGpromotions. - Broadcast promotions require the
LOYALTYpromotion type, theBROADCASTcategory, and theBulkEMFEventtrigger. - A
SINGLEactivity supports at most one milestone. - For
GROUPactivities, if a common cycle action mapping is populated, child activities must not have their own individual mappings.
Example request
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic 5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=BC9cwq9x9u_qIzIGlUxLEwV1ldTNVbpH1faK4-1763285329155-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Daily Perks - Spend 50 Get 100 Points",
"description": "Spend over $50 in a single transaction to get 100 bonus points. Limited to once per user per day.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "daily-perks-spend-50-get-100-points",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups":[]
},
"activities":[
{
"id": "activity_1763300000001",
"type": "SINGLE",
"name": "Spend Over $50",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \">\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"real:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"transaction:object:primitive\",\n \"value\": \"currentTransaction\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"real:object:primitive\",\n \"value\": \"amount\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"number:primitive\",\n \"value\": \"50\"\n }\n ]\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_award_points",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award 100 Bonus Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109006",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones": []
}
],
"limits":[
{
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "COUNT",
"limitValue": 1,
"period": {
"periodType": "MOVING_WINDOW",
"periodUnit": "DAYS",
"periodValue": 1
}
}
],
"liabilityOwnerSplitInfo":[
{
"liabilityOwnerId": 82,
"componentType": "PROMOTION",
"ratio": 100,
"active": true,
"liabilityOwnerName": "DocDemoDefaultProgram",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
}
],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'API Quick Reference
{{https://eu.api.capillarytech.com/v3/promotions}}
└─ {{CreateLoyaltyPromotionRequest}}
├─ {{metadata}} (Object)
│ ├─ {{name}} (string)
│ ├─ {{description}} (string)
│ ├─ {{orgId}} (integer)
│ ├─ {{programId}} (string)
│ ├─ {{startDate}} (string)
│ ├─ {{endDate}} (string)
│ ├─ {{promotionType}} (string)
│ ├─ {{status}} (enum)
│ ├─ {{timezoneName}} (string)
│ ├─ {{promoIdentifier}} (string)
│ ├─ {{promotionCategory}} (string, Conditional — broadcast only)
│ └─ {{promotionMetadata}}[]
├─ {{customerEnrolment}} (Object)
│ ├─ {{enrolmentMethod}} (enum)
│ ├─ {{audienceGroups}}[]
│ └─ {{customerEligibilityType}} (enum)
├─ {{activities}}[]
│ ├─ {{id}} (string)
│ ├─ {{type}} (enum)
│ ├─ {{name}} (string)
│ ├─ {{event}} (string)
│ ├─ {{expJSON}} (string)
│ ├─ {{cycles}}[]
│ ├─ {{commonCycleActionMapping}} []
│ ├─ {{activityCycles}}[]
│ ├─ {{milestones}} []
│ └─ {{children}}[]
├─ {{workflowMetadata}} (Object)
│ ├─ {{enrolment}} (Object)
│ └─ {{optin}} (Object)
├─ {{limits}}[]
│ ├─ {{entityScope}} (enum)
│ ├─ {{granularity}} (enum)
│ ├─ {{actionType}} (enum)
│ ├─ {{actionSubTypeId}} (string)
│ ├─ {{limitType}} (enum)
│ ├─ {{limitValue}} (number)
│ └─ {{period}} (Object)
├─ {{liabilityOwnerSplitInfo}}[]
│ ├─ {{orgId}} (integer)
│ ├─ {{liabilityOwnerId}} (integer)
│ ├─ {{componentType}} (enum)
│ ├─ {{ratio}} (number)
│ ├─ {{liabilityOwnerType}} (enum)
│ └─ {{active}} (boolean)
├─ {{comments}} (string)
├─ {{broadcastMetadata}} (Object, Conditional — broadcast only)
│ ├─ {{source}} (string)
│ └─ {{audienceFilter}} (Object)
│ └─ {{audienceListIds}} (Array of integer)
└─ {{promotionSchedule}} (Object, Conditional — broadcast only)
└─ {{schedule}} (Object)
├─ {{startType}} (enum)
├─ {{scheduleDate}} (string, Conditional)
└─ {{frequency}} (enum)Prerequisites
- Authentication: Basic or OAuth authentication.
- Default access group
Request body parameters
| Field | Type | Required | Description |
|---|---|---|---|
| metadata | Object | Yes | Contains all core promotion settings. Specifies the essential configuration details for the promotion. This object holds the core identifiers and timing of a promotion, such as the name of the promotion, the duration of the promotion, and the promotion type, among others. See the metadata Object table below. |
| Metadata Object | |||
| .name | string | Yes | Specifies the unique name of the promotion, used for identification. Max length: 200. Example: "Q3 Bonus Points for Gold Tier" |
| .orgId | integer | Yes | Indicates the unique organization identifier the promotion belongs to. This ensures the promotion runs under the correct business account. To retrieve the orgId, use theGet Loyalty Programs API. |
| .startDate | string | Yes | Defines the promotion's start date in ISO 8601 format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India. Format for the request parameter: 2025-12-16T14:30:45+05:30. |
| .endDate | string | Yes | Defines the promotion's end date in ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on December 31, 2025, in India. Format for the request parameter: 2025-12-31T23:59:59+05:30. |
| .promotionType | string | Yes | Indicates the nature of the reward or promotion type, used for categorisation. Supported values :LOYALTY_EARNING: Use this promotion type when the primary reward is awarding loyalty points or currency to the customer. LOYALTY: Use this promotion type when customers are explicitlyenrolled (via import or audience filter) and no opt-in is required. GENERIC: Use this promotion type for any non-point reward, such as issuing a voucher, awarding a badge, or upgrading a customer's tier, where enrollment is automatic via transaction and no explicit opt-in or enrollment workflow is needed.For broadcast promotions, set promotionType to LOYALTY. |
| .status | enum | Yes | Specifies the initial status upon creation, determining its visibility and execution state. Supported Values: DRAFT: Promotion is saved but is not active.ACTIVE: Promotion is live and active.PENDING_APPROVAL: Promotion is awaiting approval and is not active. |
| .description | string | Optional | Indicates a brief description of the promotion's purpose for internal reference. E.g., "Standard weekend points multiplier promotion". |
| .programId | string | Optional | Specifies the loyalty program unique identifier to which the promotion is associated with, linking it to that program's points system. To retrieve the programId, use the Get Loyalty Programs API. |
| .timezoneName | string | Optional | Specifies the timezone name for the promotion's schedule. This is a reference label to identify the timezone where the promotion was created. If this values is not provided, the value is stored as null in the API response and the organisation timezone is used as the reference timezone name. Supported Values: Valid IANA Time Zone Database name.Example: "Asia/Kolkata" or "America/New_York" |
| .promoIdentifier | string | Optional | Specifies a unique string identifier for the promotion. You can use this identifier to search and identify a specific promotion. Max length: 255 characters. |
| .promotionCategory | string | Conditional | Identifies the promotion variant. Set to BROADCAST for broadcast promotions. Omit or leave null for standard activity-based promotions. Required when creating a broadcast promotion. |
| .promotionMetadata | Array (Object) | Optional | Defines a list of custom key-value pairs for additional metadata, often for reporting or integration purposes. Supported Values: Array of PromotionMetadata objects. Example: [ { "key": "PromotionCode", "value": "FALL25" } ]See the promotionMetadata Object table below for the full structure. This object captures optional metadata for internal promotion tracking. It lets you add a key–value pair to label or identify the promotion. |
| promotionMetadata Object | |||
| ..isBrandDefined | string | Optional | Indicates if the metadata key is custom (true) or system-defined (false). True indicates that the metadata key is user-defined and not internally generated. |
| ..key | string | Optional | Specifies the custom metadata key name. This key is used for tracking internal promotions. Example: "PromotionCode" |
| ..value | string | Optional | Specifies the metadata key value. This value is used for the specific code for the promotion. Example: "FALL25" |
| customerEnrolment | Object | Yes | Defines who is initially eligible. See the Customer Enrolment Object table below. Specifies the configuration for how customers enrol into the promotion and whom to target. It specifies how customers first enrol, whether they join automatically via transactions, through a manual list import, or based on existing audience segments. |
| Customer Enrolment Object | |||
| .enrolmentMethod | enum | Optional | Defines the primary enrollment type. TRANSACTION: Auto-enrolls the customer when any purchase is made.Example: A cafe's "December Holiday Bonus" promo. Any customer who makes purchases during December is automatically enrolled and starts earning. IMPORT: Manually enrols a specific list.Example: A brand wants to reward 50 specific contest winners. The marketer uploads a CSV file containing those 50 customer IDs, and only those 50 people will be enrolled. |
| .audienceGroups | Array (Object) | Conditional | List of audience segments. For audience-based enrolment, configure workflowMetadata.enrolment.basedOn = AUDIENCE with enrolmentMethod = IMPORT. |
| ..audienceGroupId | integer | Yes | The ID of the target audience group. Example: 12345 |
| ..audienceGroupName | string | Optional | Informational name of the audience group. Example: "Gold Tier" |
| ..description | string | Optional | Informational description of the audience group. Example: "High spending customers" |
| .customerEligibilityType | enum | Optional | Restricts which customers are eligible for the promotion based on their loyalty enrollment status. Supported Values: LOYAL: Only customers with active loyalty enrollment can qualify. Use this for exclusive member rewards.NON_LOYAL: Only customers without active loyalty enrollment can qualify. Use this for acquisition promotions to convert non-members.ALL: All customers can qualify regardless of enrollment status.Default value: ALL |
| workflowMetadata | Object | Optional | Defines dynamic opt-in or enrollment rules. See the workflowMetadata Object table below. Defines the rules that determine how customers can join or opt in to the loyalty promotion, whether through automatic, system-driven enrollment or through customer-initiated participation. Note: Ignored for broadcast promotions ( promotionCategory: BROADCAST). Do not include workflowMetadata in broadcast promotion payloads. |
| workflowMetadata Object | |||
| .enrolment | Object | Optional | Specifies rules for automatic dynamic enrollment. |
| .optin | Object | Optional | Specifies rules for customer-managed opt-in. |
| ..optInStartDate | String | Conditional | Start of the opt-in window in ISO 8601 (YYYY-MM-DDTHH:MM:SSZ) format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30. This date should be within the time-frame of the loyalty promotion. This is supported only for LOYALTY_EARNING type promotions when the CONF_ENROLMENT_OPTIN_DURATION_ENABLED org flag is enabled. To enable this raise a JIRA ticket to the Capillary support team. Once the promotion is live, this value is locked on all subsequent versioned drafts. |
| ..optInEndDate | String | Conditional | End of the opt-in window in ISO 8601 (YYYY-MM-DDTHH:MM:SSZ) format, including the region offset. For example: The end date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30. This date should be within the time-frame of the loyalty promotion. This is supported only for LOYALTY_EARNING type promotions when the CONF_ENROLMENT_OPTIN_DURATION_ENABLED org flag is enabled. To enable this raise a JIRA ticket to the Capillary support team. Once the promotion is live, this value is locked on all subsequent versioned drafts. |
| broadcastMetadata Object | |||
| broadcastMetadata | Object | Conditional | Defines audience targeting for a broadcast promotion. Required when promotionCategory is BROADCAST. Not applicable for activity-based promotions. |
| .source | string | Yes | Specifies the audience source type. Supported value: AUDIENCE_FILTER. |
| .audienceFilter | Object | Yes | Contains the audience filter configuration. |
| ..audienceListIds | Array (integer) | Yes | List of audience group IDs to receive the reward. At least one ID is required. Example: [1130180] |
| .tillId | integer (int64) | Conditional | The ID of the till used to issue rewards for the broadcast. Required for broadcast promotions. Obtain from your org configuration. |
| promotionSchedule Object | |||
| promotionSchedule | Object | Conditional | Defines the delivery schedule for a broadcast promotion. Required when promotionCategory is BROADCAST. |
| .schedule | Object | Yes | Specifies when and how frequently rewards are issued. |
| ..startType | enum | Yes | Defines when the broadcast starts after approval. Supported values: IMMEDIATE: Starts immediately after the promotion is approved.PARTICULAR_DATE: Starts at a specific date and time defined in scheduleDate. |
| ..scheduleDate | string | Conditional | Defines the promotion's start date in ISO 8601 format, including the region offset. For example: The start date is at 09:00:00 on June 01, 2026, in India. Format for the request parameter: 2026-06-01T09:00:00+05:30. Required when startType is PARTICULAR_DATE. |
| ..frequency | enum | Conditional | Specifies how often rewards are issued. Supported values: ONCE: Rewards are issued a single time.DAILY: Rewards are issued once per day until the promotion endDate. |
| activities | Array of Object | Yes | Defines the triggers and rewards. Specifies the definitions for what actions a customer must perform to qualify, including the specific events to listen for and the rules to evaluate. Contains both common fields, single activities, and group activities logic. |
| Activities Object | |||
| .id | string | Optional | Unique identifier for the activity. Any unique string is valid — the server does not enforce a specific format and does not auto-assign an ID if omitted. The pattern activity_<epoch timestamp> shown in examples is a convention, not a requirement. Example: "activity_1761023957829" |
| .type | enum | Yes | SINGLE: A single trigger. GROUP: A combination of triggers. Supported Values: SINGLE, GROUP. |
| .name | string | Optional | Name for identification. Example: "Main Purchase Activity" |
| .parentId | string | Optional | ID of the parent if this is a array of objects of activity inside a GROUP. Example: "activity_group_parent" |
| .rulesetId | string | Optional | System-assigned identifier for the Points Engine ruleset associated with this activity. Populated by the backend after the promotion is published. Pass this back when editing an existing activity. |
| .cycles | Array (Object) | Optional | Defines general time windows (cycles) for this activity. |
| ..id | string | Optional | Cycle ID. Example: "c1" |
| ..name | string | Optional | Cycle name. Example: "Nov Cycle" |
| ..startDate | string | Optional | Defines the cycle's start date in ISO 8601 format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India. Format for the request parameter: 2025-12-16T14:30:45+05:30. |
| ..endDate | string | Optional | Defines the cycle's end date in ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on December 31, 2025, in India. Format for the request parameter: 2025-12-31T23:59:59+05:30. |
| .commonCycleActionMapping | Array (Object) | Optional | Maps reward actions directly to cycles for this activity. Use this when the promotion rewards customers on every qualifying event with no target threshold to hit. Leave this empty and populate milestones instead when the reward is conditional on reaching a defined target (e.g., spend $500, complete 10 check-ins). |
| ..cycle | string | Optional | ID of the cycle this action applies to. Example: "main_cycle" |
| ..defaultValue | number | Optional | A default value (e.g., a target amount) used in action calculations. Example: 10.0 |
| ..startDate | string | Optional | Defines the mapping's start date in ISO 8601 format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India. Format for the request parameter: 2025-12-16T14:30:45+05:30. |
| ..endDate | string | Optional | Defines the mapping's end date in ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on December 31, 2025, in India. Format for the request parameter: 2025-12-31T23:59:59+05:30. |
| ..rulesetId | string | Optional | Specific ruleset just for this action mapping. |
| ..actions | Array (Object) | Optional | Object containing details of the action to trigger for the loyalty promotion. |
| ...id | string | Optional | Client-supplied temporary identifier for this action. Used to reference the action within the request payload and is not persisted as the system's internal ID. Example: "temp_06a1a899-99e8-4f5e-8910-a3b2b51aa142" |
| ...actionName | string | Optional | Specify the action to trigger for the loyalty promotion. Supported values: See delegateActionClass Values for the complete list. |
| ...actionClass | string | Optional | Always com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl. The actual implementation is determined by delegateActionClass in mandatoryPropertiesValues. |
| ...description | string | Optional | A brief label for this action. Example: "Advanced currency allocation action" |
| ...mandatoryPropertiesValues | Object | Optional | Key-value pairs that configure the action. Required keys vary by actionName. |
| ....delegateActionClass | string | Optional | The entire implementation class for the action. Must correspond to the actionName. See delegateActionClass Values for the complete list. |
| ....PointsRoundingStrategy | string | Optional | Controls how the final points amount is rounded. Supported values: ACTUAL (rounds to nearest half-up, default), FLOOR (always rounds down), ROUND (rounds to nearest), ROUND_TO_NEAREST (rounds to nearest half-down). |
| ....SourceValueRoundingStrategy | string | Optional | Controls how the source value (e.g. bill amount) is rounded before points calculation. Supported values: ACTUAL (no rounding, default), FLOOR (always rounds down), ROUND (rounds to nearest), ROUND_TO_NEAREST (rounds to nearest half-down). |
| ....DelayStrategy | string | Optional | Controls when points are accrued. Supported values: AS_DEFINED_IN_ALLOCATION_STRATEGY (default), FIXED_DELAY_FROM_ITEM_RETURN_PERIOD, ON_EXTERNAL_TRIGGER, FIXED_DELAY_FROM_TXN_ITEM_EXT_FIELD, ACCRUAL_DATE_AS_PER_BE_ATTRIBUTE, ACCRUAL_DATE_FROM_TXN_ITEM_EXT_FIELD, FIXED_DELAY_FROM_BE_ATTRIBUTE. |
| ....ProRateOnSourceValue | string | Optional | Determines the base value used when prorating points. Supported values: EVENT_DEFAULT_VALUE (default), AMOUNT, QUANTITY, LINEITEM_AMOUNT, LINEITEM_QUANTITY, TRACKED_VALUE, TRACKER_EVALUATION, CURRENT_AGGREGATE, PREVIOUS_AGGREGATE, DEFINED_TARGET, ACHIEVED_VALUE, ACHIEVED_VALUE_MINUS_DEFINED_TARGET, GENERIC_EVENT_FIELD_VALUE, TRANSACTION_EXTENDED_FIELD, LINEITEM_EXTENDED_FIELD, CUSTOMER_EXTENDED_FIELD, CUSTOMER_CUSTOM_FIELD, GAP_TO_UPGRADE, GAP_TO_UPGRADE_AFTER_EVENT, CURRENT_EVENT_TRACKED_VALUE, EXCESS_AFTER_UPGRADE. |
| ....PointType | string | Optional | Specifies which point category is awarded. Valid values are the point type names configured for the org. Example: Main (the primary loyalty points type). |
| ....Currency | string | Optional | Points currency type. POINTS (standard loyalty points, default) or any org-configured alternate currency identifier (e.g. MILES, CASHBACK). |
| ....ProrateFieldName | string | Optional | The exact field name used for field-based proration. Only relevant when ProRateOnSourceValue is TRANSACTION_EXTENDED_FIELD, LINEITEM_EXTENDED_FIELD, or similar. Leave blank if not applicable. |
| ...mandatoryComplexPropertiesValues | Object | Optional | Object containing details on line-item filter conditions used to restrict award eligibility to specific products or categories. Only populated for actions that support line-item filtering, for example, currency earn actions, badge earn actions. |
| ...embeddedStrategies | Array (Object) | Optional | Object containing details on inline strategy configurations (point allocation and expiry) attached to this action. |
| ....strategyTypeId | integer (int32) | Optional | Identifies the strategy type. Supported values:1: Allocation strategy — controls how points are calculated and awarded (e.g. multiplier, fixed points, prorated).3: Expiry strategy — defines when the awarded points expire. |
| ....propertyValues | string | Optional | JSON string containing the configuration properties for the strategy. Keys and values depend on the strategyTypeId. Strategy configurations are created and managed in the Capillary platform. Once created, reference them here using their system-assigned IDs. |
| ....owner | string | Optional | The system that owns this strategy. Supported values: LOYALTY, CAMPAIGN. |
| .event | string | Yes/Optional | For SINGLE: The exact event name that triggers the activity. For GROUP: The event that applies to the group as a whole. Built-in system events: TransactionAdd (purchase completed), GroupTransactionAdd (group purchase), TransactionFinished (transaction finalised), NewBill (new bill created), SlabUpgrade (customer tier upgraded).Custom org-configured events (e.g., GymCheckIn, FeedbackSubmitted) are also supported. Custom event names are defined per org and are not fixed by the platform. See Creating a custom behavioral event.For broadcast promotions, this must be BulkEMFEvent. The backend auto-sets this value even if not specified. |
| .ruleExpression | string | Optional | Specifies the rule expression string (DSL) to filter the triggering event (DSL string conforming to rule grammar). For GROUP: Rule expression that applies to the group result. |
| .expJSON | string | Optional | Specifies the JSON representation of the loyalty rule expression. (Valid JSON rule structure string). To generate an expJSON from a loyalty workflow expression use the Generate Expression JSON API. |
| .frequencyType | string | Optional | Specifies the time unit for milestone evaluation. Supported values: DAILY: Tracks and resets progress every day. Example: "Login once a day to earn a streak badge." WEEKLY: Tracks and resets progress every week. Example: "Visit the gym 3 times this week to get bonus points." MONTHLY: Tracks and resets progress every month. Example: "Spend $500 in November to unlock a voucher." QUARTERLY: Tracks and resets progress every quarter. HALF_YEARLY: Tracks and resets progress every half year. YEARLY: Tracks and resets progress every year. CUSTOM: Uses a custom-defined frequency period. |
| .targetEvaluationType | enum | Optional | Specifies the evaluation logic window:FIXED_CALENDAR_WINDOW: Tracks progress within the specific start and end dates set for the milestone, regardless of the broader promotion duration.Example: "Spend $500 specifically between December 1st and December 15th to get a bonus." CYCLIC_WINDOW: Tracks and resets progress based on the custom time intervals defined in your activityCycles list.Example: "Complete 3 tasks during 'Phase 1' (Jan 1-10) and then 3 tasks during 'Phase 2' (Jan 20-30)." PERIOD_AGNOSTIC_WINDOW: Tracks cumulative progress over the entire duration of the promotion without ever resetting.Example: "Reach a total of 50 visits at any point during the year-long promotion to become a VIP." CALENDAR_CYCLIC_WINDOW: Tracks progress based on standard calendar units (like days or weeks) that repeat automatically.Example: "Make a purchase every Sunday (Weekly cycle) to earn double points." |
| .targetCycleStartDate | string (date-time) | Optional | Defines the target cycle's start date in ISO 8601 format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India. Format for the request parameter: 2025-12-16T14:30:45+05:30. |
| .targetCycleEndDate | string (date-time) | Optional | Defines the target cycle's end date in ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on December 31, 2025, in India. Format for the request parameter: 2025-12-31T23:59:59+05:30. |
| .activityCycles | Array (Object) | Optional | Defines specific, named time periods used by a milestone. |
| ..id | string | Optional | Specifies the activity cycle ID. |
| ..name | string | Optional | Specifies the activity cycle name. |
| ..startDate | string | Optional | Defines the activity cycle's start date in ISO 8601 format, including the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India. Format for the request parameter: 2025-12-16T14:30:45+05:30. |
| ..endDate | string | Optional | Defines the activity cycle's end date in ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on December 31, 2025, in India. Format for the request parameter: 2025-12-31T23:59:59+05:30. |
| ..refCode | string | Optional | Specifies the activity cycle reference code. |
| ..isActive | boolean | Optional | Indicates if the activity cycle is active. Supported values : true , false |
| .milestones | Array (Object) | Optional | Definesmilestones (targets) within this activity. Use milestones when the reward is conditional on reaching a defined threshold (e.g., spend $500, complete 10 check-ins). Leave this empty and use commonCycleActionMapping instead when the reward fires on every qualifying event with no threshold. A SINGLE activity supports at most one milestone. |
| ..name | string | Optional | Specifies the milestone name. Supported Values: String. Example: "Tier 1: Spend $100" |
| ..sameActionsForEveryCycle | boolean | Optional | Specifies if the same actions apply across all cycles defined for this milestone. Supported Values:true: The same reward will be given every time a cycle is completed. false: You can define different reward for each specific cycle. |
| ..differentTargetsForEveryCycle | boolean | Optional | Specifies if target values differ across cycles. Supported Values: true: The target value (e.g., spend $100) can be different for each cycle.false: The target value is the same for all cycles. |
| ..description | string | Optional | Indicates the milestone description. Supported Values: String. Example: "Reward for reaching the first spending level" |
| ..trackingType | string | Optional | Specifies how the milestone is tracked. Supported Values:DEFAULT: Tracks simple cumulative progress towards a single target.STREAKS: Tracks consecutive event occurrences (e.g., "Visit 3 days in a row").NON_CONTINUOUS_STREAKS: Tracks streak occurrences that do not need to be consecutive.CAPPING: Applies a cap on how much progress can accumulate within a period.UNIFIED: Tracks progress across a unified set of targets within the same milestone group. |
| ..targetType | enum | Yes | Defines the KPI to track for the milestone. Supported Values:QUANTITY: Tracks the total number of items purchased (e.g., buy 10 t-shirts). SALES: Tracks the net sales value of transactions, after discounts (e.g., spend $100). * COUNT: Tracks the number of times a specific event occurs (e.g., 3 check-ins). * VISIT: Tracks the number of unique days a customer performs an action. * GROSS_SALES: Tracks the total sales value before any discounts are applied. * REGULAR_POINTS: Tracks the total "Regular" (base) points earned by the customer. * PROMOTIONAL_POINTS: Tracks the total "Promotional" (bonus) points earned by the customer. * ALL_POINTS: Tracks the sum of both "Regular" and "Promotional" points earned. * EXTENDED_FIELD: Tracks a custom data field sent with the transaction. When using this value, you must also populate the targetRuleMetaData object. * EVENT_ATTRIBUTE: Tracks a specific attribute from the incoming event's data payload. * REGULAR/PROMOTIONAL/ALL: Aliases for the respective points types. |
| ..targetEntity | enum | Yes | Specifies the entity to track the targetType against. Supported Values: TRANSACTION: Tracks data at the overall transaction level (e.g., total bill amount). LINEITEM: Tracks data at the individual product level (e.g., quantity of a specific SKU). * POINTS: Tracks data based on points earned (e.g., earn 500 points). * EVENT: Tracks data from a non-transactional event (e.g., a gym check-in). * ALTERNATE_CURRENCIES: Tracks a custom-defined currency (e.g., "Coins" or "Gems"). |
| ..targetRuleMetaData | Object | Conditional | Required when targetType is EXTENDED_FIELD. Defines which custom extended field to track and how to aggregate its values across line items or events. |
| ...name | string | Yes | The name of the extended field to track. Must match an extended field configured for the org. Example: "CentralGST" |
| ...aggregateFunction | enum | Yes | Specifies how to aggregate the extended field values. Supported values: SUM: Adds all values together (e.g., total GST across all line items).COUNT: Counts the number of non-null occurrences.MAX: Uses the highest value found.MIN: Uses the lowest value found. |
| ..defaultValue | string | Optional | Specifies the default target value threshold for achieving the milestone. Although the field type is string, it holds a numeric value. Example: "15" for 15 transactions, "1000" for a $1000 spend target. |
| ..targetValue | string | Optional | Specifies the target value to achieve the milestone (often same as defaultValue). Supported Values: String representing a number. |
| ..preferredTillId | integer (int64) | Optional | Indicates a preferred till ID if tracking is specific to certain POS terminals. |
| ..frequencyType | string | Optional | Specifies the time unit for milestone evaluation. Supported Values: DAILY: Tracks and evaluates progress in daily blocks.WEEKLY: Tracks and evaluates progress in weekly blocks.MONTHLY: Tracks and evaluates progress in monthly blocks.QUARTERLY: Tracks and evaluates progress in quarterly blocks.HALF_YEARLY: Tracks and evaluates progress in half-yearly blocks.YEARLY: Tracks and evaluates progress in yearly blocks.CUSTOM: Uses a custom-defined frequency period. |
| ..targetEvaluationType | enum | Optional | Specifies the evaluation logic window. Supported Values:FIXED_CALENDAR_WINDOW: Uses defined start/end dates for the entire milestone.eg. Counter resets every Monday or on the 1st of every month. CYCLIC_WINDOW: Resets progress based on cycles defined in activityCycles or milestone periods.eg. Progress resets at the start of Nov Week 2 (based on pre-configured cycle dates). * PERIOD_AGNOSTIC_WINDOW: Evaluates over the entire promotion duration without any resets.eg. Counter never resets; must achieve the goal at any time during the promotion. * CALENDAR_CYCLIC_WINDOW: Combines calendar and cyclic logic.eg. Resets counting after every 30 days of activity |
| ..recurringCycles | integer (int32) | Optional | Specifies the number of recurring cycles for milestone evaluation. |
| ..targetGroupId | integer (int64) | Optional | Indicates the target group ID associated with this milestone's tracking logic. |
| ..leaderboardEnabled | boolean | Optional | Indicates if a leaderboard competition is enabled for this milestone. Supported Values: true: A leaderboard is active for this milestone.false: No leaderboard is active. |
| .combinationType | enum | Yes | Logic to combine children in GROUP activities. Supported Values: ANY, ALL. |
| .children | Array (Object) | Yes | An array of child Activity objects (SINGLE or nested GROUP). Note: When a GROUP activity has commonCycleActionMapping populated, it takes precedence and is used as the reward definition for the entire group. Child activities in a GROUP must not have their own commonCycleActionMapping — this is enforced by the server. |
| limits | Array of Object | Optional | Sets usage limits. See the limits Object table below. Specifies limits for issuance and redemption. This is an array, so you can define multiple limit objects. |
| Limits Object | |||
| .entityScope | enum | Optional | Specifies the scope of the limit. Supported values: PROMOTION: The limit applies only to rewards generated by this specific promotion. PROGRAM: The limit applies across the entire loyalty program, affecting rewards from all promotions sharing this program IDDefault Values: PROMOTION. |
| .entityId | integer | Conditional | The numeric ID of the entity this limit applies to. Required when entityScope is PROGRAM — set this to the programId. Not required when entityScope is PROMOTION. |
| .granularity | enum | Optional | Specifies the tracking level for the limit. Supported values: OVERALL: Limits the total count/sum across all customers combined. USER: Limits the count/sum per individual customer. PER_ACTIVITY: Limits the count/sum based on each individual triggering activity instance. |
| .actionType | enum | Optional | Specifies the category of action to cap. This restricts the limit to only apply when a specific type of action occurs. Supported values: AWARD_CURRENCY: Limits points or currency awards (e.g., cap total points a customer can earn).AWARD_BADGE: Limits badge awards.ISSUE_COUPON: Limits coupon or voucher issuance (e.g., cap how many coupons a customer can receive).ISSUE_REWARD: Limits reward issuance from the rewards catalog.UPGRADE_TIER: Limits tier upgrade actions.RENEW_TIER: Limits tier renewal actions.DOWNGRADE_TIER: Limits tier downgrade actions. |
| .actionSubTypeId | string | Optional | Specifies the limit to a specific sub-type. -If actionType is AWARD_CURRENCY, this could be the currency name like "Points" or "Miles".-If actionType is ISSUE_COUPON, this could be the coupon series ID like "FALLSALE25". |
| .limitType | enum | Optional | Specifies the measure used for limiting. Supported values: SUM: Limits the total value accumulatedEg. maximum 1000 points total. COUNT: Limits the total number of times an action can occurEg. maximum 1 redemption. |
| .limitValue | number | Optional | Specifies the maximum allowable value for the limit. If limitType is COUNT, this is the max number of times. If limitType is SUM, this is the max total value. |
| .period | Object | Conditional | Defines the reset window. Required if you need to set a reset interval for limits. See the period Object table below for full structure. Defines the time window and reset logic for a limit. |
| period Object | |||
| ..periodType | enum | Optional | Defines the reset style for the limit. Supported values: NON_PERIOD_BASED: The limit applies once for the entire promotion duration and never resets.MOVING_WINDOW: Uses a rolling duration from the current moment. Eg. "last 7 days".FIXED_CALENDAR_WINDOW: Resets based on fixed calendar periods aligned to specific dates or calendar boundaries. This type supports three variations:Every X Days with Reference Date ( periodUnit = DAYS): Divides time into fixed X-day periods starting from a reference date. Eg. "Every 5 days starting from January 1st."Every Week Starting on Specific Day ( periodUnit = WEEKS with periodStartDay): Weeks begin on the specified day. Eg. "Every week starting Monday." Note: periodValue must be 1 when using periodStartDay.* Every Calendar Month ( periodUnit = MONTHS): Periods align to calendar month boundaries (1st to last day). Eg. "Every month" means January 1-31, February 1-28/29, etc.FIXED_WINDOW: The limit is only active during the specific startDate and endDate defined below. |
| ..periodUnit | enum | Optional | Specifies the unit of time if periodType is MOVING_WINDOW or FIXED_CALENDAR_WINDOW.DAYS: Resets daily.WEEKS: Resets weekly.MONTHS: Resets monthly. |
| ..periodValue | integer | Optional | Specifies the number of period units that define one complete limit period. For periodType = MOVING_WINDOW: The number of days/weeks/months in the rolling window. Example: periodValue = 7 with periodUnit = DAYS means "last 7 days". For periodType = FIXED_CALENDAR_WINDOW with periodUnit = DAYS: The number of days in each fixed period. Example: periodValue = 5 means divide time into 5-day chunks from the reference date. * For periodType = FIXED_CALENDAR_WINDOW with periodUnit = WEEKS: Must be 1 when periodStartDay is specified. Can be greater than 1 when using referenceDate without periodStartDay. * For periodType = FIXED_CALENDAR_WINDOW with periodUnit = MONTHS: The number of months in each period. Example: periodValue = 1 means each calendar month is a separate period. |
| ..periodStartDay | enum | Optional | Specifies which day the calendar week starts on. Supported Values: SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY.Usage Rules: When periodType is FIXED_CALENDAR_WINDOW and periodUnit is WEEKS: Optional. Defines the day of the week when each period begins. If specified, periodValue must equal 1. When periodType is FIXED_CALENDAR_WINDOW and periodUnit is DAYS or MONTHS: Must be null. Not applicable for daily or monthly periods. * When periodType is MOVING_WINDOW: Not supported. |
| ..referenceDate | string (date-time) | Optional | Specifies the anchor date used to calculate fixed calendar periods when periodType is FIXED_CALENDAR_WINDOW. All period boundaries are calculated relative to this date.For periodUnit = DAYS: The reference date serves as the starting point for dividing time into fixed X-day chunks. If the event occurs before the reference date, the system calculates backward periods. If no reference date is provided, the promotion start date is used as the anchor.For periodUnit = MONTHS: The reference date determines the anchor month. All subsequent period boundaries align to calendar month boundaries starting from the month containing this date.For periodUnit = WEEKS without periodStartDay: The reference date serves as the week boundary anchor.Note: This field is not used when periodStartDay is specified for weekly periods, as the week start day determines the boundaries.In ISO 8601 format, including the region offset. For example: The reference date is at 00:00:00 on January 1, 2025. Format for the request parameter: 2025-01-01T00:00:00+05:30.Required when periodType is FIXED_CALENDAR_WINDOW and periodUnit is DAYS or MONTHS (unless using periodStartDay for weeks). |
| ..startDate | string (date-time) | Optional | The meaning of this field depends on periodType:For periodType = FIXED_WINDOW: The exact date/time this limit becomes active, in UTC. The limit only applies to events occurring between startDate and endDate.For periodType = FIXED_CALENDAR_WINDOW: This field serves as the referenceDate - the anchor point for calculating fixed calendar periods. Not used for defining when the limit is active (the promotion's start/end dates define that).For other periodType values: Not applicable.In ISO 8601 format, including the region offset. For example: The start date is at 00:00:00 on November 01, 2025. Format for the request parameter: 2025-11-01T00:00:00+05:30. |
| ..endDate | string (date-time) | Optional | The meaning of this field depends on periodType:For periodType = FIXED_WINDOW: The exact date/time when this limit becomes inactive, in UTC. The limit only applies to events occurring between startDate and endDate.For periodType = FIXED_CALENDAR_WINDOW: Must be null. Not applicable for FIXED_CALENDAR_WINDOW.For other periodType values: Not applicable.In ISO 8601 format, including the region offset. For example: The end date is at 23:59:59 on November 30, 2025. Format for the request parameter: 2025-11-30T23:59:59+05:30. |
| liabilityOwnerSplitInfo | Array of Object | Optional | Defines cost splitting within programs and partner programs. See the LiabilityOwnerSplitInfo Object table below. Defines how the reward liability (cost) is financially distributed. This is an array, so you can define multiple split objects. |
| LiabilityOwnerSplitInfo Object | |||
| .orgId | integer | Optional | The Organization ID of the entity bearing this portion of the cost. Supported Values: A valid integer orgId. |
| .liabilityOwnerId | integer | Optional | The specific ID of the entity that owns this liability. If liabilityOwnerType is PROGRAM, this is the Program ID. If liabilityOwnerType is PARTNER, this is the Partner ID. Obtain this value from your loyalty program or partner configuration in the Capillary platform. Supported Values: A valid Program or Partner ID. Example: 229 (representing the "Diamond" program). |
| .componentType | enum | Optional | Specifies what this liability split is for. PROMOTION: (Default) The cost split applies only to this specific promotion. PROGRAM: The split applies to the entire program. |
| .ratio | number | Optional | The percentage (0-100) of the total liability this owner will cover. The sum of all ratio values in the liabilityOwnerSplitInfo array should equal 100. Supported Values: Number between 0 and 100. Example: 50 (for 50%). |
| .liabilityOwnerType | enum | Optional | Specifies if the owner is an internal program or an external partner. PROGRAM: Liability is assigned to one of your own loyalty programs. PARTNER: Liability is assigned to an external partner entity. |
| .active | boolean | Optional | Indicates if this specific split rule is active. If set to false, this split entry is ignored. Supported Values: true, false. Example: true |
| .liabilityOwnerName | string | Optional | The display name of the liability owner entity. Example: "DocDemoDefaultProgram" |
| comments | string | Optional | Internal comments for the promotion. Example: "Initial draft for review" |
Example response
{
"data": {
"metadata": {
"name": "Efd Activity Based Prom11",
"description": "Enrollment for all members, requires activity-based opt-in.",
"programId": "HiddenGemDefaultProgram_ID",
"orgId": 51174,
"startDate": "2025-11-27T05:30:00+05:30",
"endDate": "2025-12-28T05:29:59+05:30",
"timezoneName": "Asia/Kolkata",
"promotionType": "LOYALTY",
"status": "DRAFT",
"promoIdentifier": null,
"promotionId": 0,
"createdOn": "2025-10-21T20:43:08+05:30",
"lastModifiedOn": "2025-10-21T20:43:08+05:30",
"createdBy": 0,
"lastModifiedBy": 0,
"version": null,
"draftDetails": null,
"promotionMetadata": null,
"commonStrategies": null
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION"
},
"activities":[
{
"type": "SINGLE",
"id": "activity_reward_trigger",
"name": "Main Reward Activity",
"commonCycleActionMapping":[
{
"cycle": "cycle_promo_period",
"actions":[
{
"id": "action_award_points",
"actionName": "AWARD_CURRENCY",
"actionClass": "com.capillary.loyalty.engine.actor.promotion.actions.AwardCurrency",
"mandatoryPropertiesValues": {
"POINTS_TO_AWARD": "100",
"CURRENCY_IDENTIFIER": "POINTS"
}
}
],
"startDate": "2025-11-27",
"endDate": "2025-12-27"
}
],
"event": "TransactionAdd",
"allCycles":[]
}
],
"comments": null,
"parentId": null,
"version": 1,
"limits": [],
"liabilityOwnerSplitInfo":[],
"id": "68f7a304fd5b970d1efaf626",
"workflowMetadata": {
"enrolment": {
"basedOn": null,
"activities": null,
"audienceMapping": null,
"restrictions": null
},
"optin": {
"basedOn": "ACTIVITY",
"audienceMapping": null,
"activities":[
{
"type": "SINGLE",
"id": "activity_optin_trigger",
"name": "Opt-in Trigger Activity",
"event": "TransactionAdd",
"allCycles": []
}
],
"restrictions": null
}
}
},
"errors": null,
"warnings": null
}Response parameters
| Field | Type | Description |
|---|---|---|
| data | Object | The main data object for the promotion. |
| .id | String | Specifies the unique system-generated identifier for the unified promotion. |
| .metadata | Object | Defines the object containing all metadata for the promotion. |
| ..name | String | Specifies the name of the promotion. |
| ..description | String | Specifies the description of the promotion. |
| ..programId | String | Specifies the program ID associated with the promotion. |
| ..orgId | Integer (int64) | Specifies the organization ID. |
| ..startDate | String (date-time) | Indicates the promotion's start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..endDate | String (date-time) | Indicates the promotion's end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..timezoneName | String | The IANA timezone name used for the promotion’s schedule. Example: "Asia/Kolkata", "America/New_York". |
| ..promotionType | String | Specifies the type of promotion. Possible values: LOYALTY_EARNING, LOYALTY, GENERIC. |
| ..status | String | Indicates the current status of the promotion. Possible values: DRAFT, PENDING_APPROVAL, ACTIVE, UPCOMING, LIVE, COMPLETED, PAUSED, STOPPED, PUBLISH_FAILED. |
| ..promoIdentifier | String | Specifies a unique string identifier for the promotion. |
| ..promotionId | Integer (int32) | Specifies the legacy numerical promotion ID. Returns 0 on creation; the actual ID is assigned only after the promotion is published. |
| ..createdOn | String (date-time) | Indicates the promotion's creation timestamp in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..lastModifiedOn | String (date-time) | Indicates the promotion's last modification timestamp in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..createdBy | Integer (int32) | Specifies the user ID of the creator. |
| ..lastModifiedBy | Integer (int32) | Specifies the user ID of the last modifier. |
| ..version | String | Specifies the version string of the promotion. |
| ..draftDetails | Object | The pending draft version of this promotion. Non-null when the promotion has a published status (ACTIVE, LIVE, PAUSED, STOPPED, or COMPLETED) and an unpublished pending draft with status DRAFT or PENDING_APPROVAL exists; the most recently modified pending draft is returned. Null when the promotion itself is in DRAFT or PENDING_APPROVAL status, or when no unpublished pending draft exists. On the list endpoint, only returned when includeDraftDetails=true is passed. |
| ...id | String | The unique identifier of the pending draft promotion. |
| ...status | String | The status of the pending draft. Possible values: DRAFT, PENDING_APPROVAL. |
| ...version | Integer (int32) | The version number of the pending draft. |
| ...lastModifiedBy | Integer (int32) | The ID of the user who last modified the pending draft. |
| ...lastModifiedOn | String (date-time) | Indicates when the draft was last modified in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..promotionMetadata | Array (Object) | Defines a list of custom key-value metadata pairs (PromotionMetadata). |
| ...isBrandDefined | String | Specifies if the metadata is defined by the brand. |
| ...key | String | Specifies the metadata key. |
| ...value | String | Specifies the metadata value. |
| ..commonStrategies | Object | Defines reusable expiry strategies at the promotion level. Returns null when no shared strategies are configured. |
| ...expiry | Array (Object) | A list of reusable expiry strategy definitions. Each entry is a StrategyInfo object with strategyTypeId: 3. |
| ....strategyTypeId | Integer (int32) | Identifies the strategy type. 1: point allocation strategy. 3: point expiry strategy. Only these two values are valid. |
| ....propertyValues | String | JSON string of strategy configuration properties. Content and keys vary by strategyTypeId. |
| ....owner | String | The system that owns this strategy. Supported values: LOYALTY (standard loyalty program), CAMPAIGN (campaign-driven promotion). |
| ....updatedViaNewUI | Boolean | Indicates if the strategy was last updated via the Capillary UI. |
| ....strategySubType | String | The strategy sub-type. DEFAULT is the standard value. |
| ..promotionMode | String | Indicates the promotion creation mode. LEGACY: created before the unified system. UNIFIED: created via the unified API (default for all new promotions). |
| .customerEnrolment | Object | Defines the customer enrollment rules. |
| ..enrolmentMethod | String | Indicates the method of customer enrollment. Possible values: TRANSACTION, IMPORT. |
| ..audienceGroups | Array (Object) | Defines a list of audience groups for enrollment (AudienceGroupDetails). |
| ...audienceGroupId | Integer (int64) | Specifies the unique ID for the audience group. |
| ...audienceGroupName | String | Specifies the name of the audience group. |
| ...description | String | Specifies the description of the audience group. |
| .activities | Array (Object) | Defines a list of activities. |
| ..id | String | Specifies the unique ID for the activity. |
| ..type | String | Specifies the type of the activity. Possible values: SINGLE, GROUP. |
| ..name | String | Specifies the name of the activity. |
| ..parentId | String | Specifies the parent activity's ID. |
| ..rulesetId | String | The system-assigned identifier for the Points Engine ruleset associated with this activity. Populated by the backend after publishing. |
| ..cycles | Array (Object) | Defines a list of general cycles. |
| ...id | string | Specifies the cycle ID. |
| ...name | string | Specifies the cycle name. |
| ...startDate | string (date-time) | Indicates the cycle's start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...endDate | string (date-time) | Indicates the cycle's end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..commonCycleActionMapping | Array (Object) | Defines action mappings for common cycles. |
| ...cycle | String | Specifies the cycle name/ID. |
| ...defaultValue | Number (double) | Specifies the default value for the action. |
| ...startDate | String (date-time) | Indicates the mapping's start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...endDate | String (date-time) | Indicates the mapping's end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...rulesetId | String | Specifies the cycle mapping ruleset ID. |
| ...actions | Array (Object) | Defines a list of actions. |
| ....id | String | Specifies the action ID. |
| ....actionName | String | Specifies the action name. Possible values: See delegateActionClass Values for the complete list. |
| ....actionClass | String | Specifies the fully qualified Java wrapper class for this action. For most point allocation and reward actions this is com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl. The actual implementation logic is determined by delegateActionClass inside mandatoryPropertiesValues. |
| ....description | String | Specifies the action description. |
| ....mandatoryPropertiesValues | Object | Key-value pairs that configure the action. Content varies by actionName. |
| .....delegateActionClass | String | The entire implementation class for the action. See delegateActionClass Values for the complete list. |
| .....PointsRoundingStrategy | String | Controls how the final points amount is rounded. Possible values: ACTUAL (rounds to nearest half-up, default), FLOOR (always rounds down), ROUND (rounds to nearest), ROUND_TO_NEAREST (rounds to nearest half-down). |
| .....SourceValueRoundingStrategy | String | Controls how the source value (e.g. bill amount) is rounded before points calculation. Possible values: ACTUAL (no rounding, default), FLOOR (always rounds down), ROUND (rounds to nearest), ROUND_TO_NEAREST (rounds to nearest half-down). |
| .....DelayStrategy | String | Controls when points are accrued. Possible values: AS_DEFINED_IN_ALLOCATION_STRATEGY (default), FIXED_DELAY_FROM_ITEM_RETURN_PERIOD, ON_EXTERNAL_TRIGGER, FIXED_DELAY_FROM_TXN_ITEM_EXT_FIELD, ACCRUAL_DATE_AS_PER_BE_ATTRIBUTE, ACCRUAL_DATE_FROM_TXN_ITEM_EXT_FIELD, FIXED_DELAY_FROM_BE_ATTRIBUTE. |
| .....ProRateOnSourceValue | String | The base value used when prorating points. Possible values: EVENT_DEFAULT_VALUE (default), AMOUNT, QUANTITY, LINEITEM_AMOUNT, LINEITEM_QUANTITY, TRACKED_VALUE, TRACKER_EVALUATION, CURRENT_AGGREGATE, PREVIOUS_AGGREGATE, DEFINED_TARGET, ACHIEVED_VALUE, ACHIEVED_VALUE_MINUS_DEFINED_TARGET, GENERIC_EVENT_FIELD_VALUE, TRANSACTION_EXTENDED_FIELD, LINEITEM_EXTENDED_FIELD, CUSTOMER_EXTENDED_FIELD, CUSTOMER_CUSTOM_FIELD, GAP_TO_UPGRADE, GAP_TO_UPGRADE_AFTER_EVENT, CURRENT_EVENT_TRACKED_VALUE, EXCESS_AFTER_UPGRADE. |
| .....PointType | String | The point category awarded. Valid values are the point type names configured for the org. Example: Main (the primary loyalty points type). |
| .....Currency | String | Points currency type. POINTS (standard loyalty points, default) or any org-configured alternate currency identifier (e.g. MILES, CASHBACK). |
| .....ProrateFieldName | String | The field name used for field-based proration. Relevant when ProRateOnSourceValue is TRANSACTION_EXTENDED_FIELD, LINEITEM_EXTENDED_FIELD, or similar. Empty string if not applicable. |
| ....mandatoryComplexPropertiesValues | Object | Returns {} for most actions. Only populated for actions that support line-item filtering — restricting awards to specific SKUs, brands, or categories. Supported on AdvanceCurrencyAllocationActionImpl and badge earn actions only. |
| ....embeddedStrategies | Array (Object) | Object containing details on inline strategy configurations (point allocation and expiry) attached to this action. |
| .....strategyTypeId | Integer (int32) | Identifies the strategy type. 1: point allocation strategy — defines how many points to award per slab. 3: point expiry strategy — defines when awarded points expire. Only these two values are valid. |
| .....propertyValues | String | JSON string of strategy configuration. For strategyTypeId 1 (allocation): allocation_type (FIXED) and allocation_values (comma-separated point amounts per slab, e.g. "100,100,100"). For strategyTypeId 3 (expiry): expiry_type (SLAB_INDEPENDENT or SLAB_BASED), expiry_from (CURRENT_DATE, CUSTOMER_ENROLLMENT_DATE, ACTIVITY_BASED_EXTENSION, MEMBERSHIP_DATE, FARTHEST_POINTS_TRANSFERRED_EXPIRY_DATE, BILL_EXTENDED_FIELD, LINEITEM_EXTENDED_FIELD, CUSTOMER_EXTENDED_FIELD), expiry_time_units (comma-separated per slab: NUM_DAYS, MONTH_END, NUM_MONTHS, NUM_MONTHS_END, YEAR_END, NUM_YEARS, NEVER, FIXED_DATE, ENROLLMENT_DATE, FIXED_DATE_WITHOUT_YEAR), expiry_time_values (date strings for FIXED_DATE; numeric duration for time-based units; "100" placeholder when NEVER). |
| .....owner | String | The system that owns this strategy. Typically LOYALTY. |
| .....strategySubType | String | The strategy sub-type. DEFAULT is the standard value. |
| ..event | String | Specifies the event associated with the activity. |
| ..ruleExpression | String | Specifies the rule expression. |
| ..expJSON | String | Specifies the rule expression in JSON format. |
| ..frequencyType | String | Specifies the time unit for milestone evaluation. Possible values: DAILY, WEEKLY, MONTHLY, QUARTERLY, HALF_YEARLY, YEARLY, CUSTOM. |
| ..targetEvaluationType | String | Specifies the evaluation logic window. Possible values: FIXED_CALENDAR_WINDOW, CYCLIC_WINDOW, PERIOD_AGNOSTIC_WINDOW, CALENDAR_CYCLIC_WINDOW. |
| ..targetCycleStartDate | String (date-time) | Indicates the target cycle's start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..targetCycleEndDate | String (date-time) | Indicates the target cycle's end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..activityCycles | Array (Object) | Defines activity-specific cycles. |
| ...id | string | Specifies the activity cycle ID. |
| ...name | string | Specifies the activity cycle name. |
| ...startDate | string | Indicates the activity cycle's start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...endDate | string | Indicates the activity cycle's end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...refCode | string | Specifies the activity cycle reference code. |
| ...isActive | boolean | Indicates if the activity cycle is active. |
| ..milestones | Array (Object) | Defines milestones. |
| ...name | string | Specifies the milestone name. |
| ...sameActionsForEveryCycle | boolean | Indicates if the same actions apply across all cycles. |
| ...differentTargetsForEveryCycle | boolean | Indicates if target values differ across cycles. |
| ...description | string | Indicates the milestone description. |
| ...trackingType | string | Specifies how the milestone is tracked. Possible values: DEFAULT, STREAKS, NON_CONTINUOUS_STREAKS, CAPPING, UNIFIED. |
| ...targetType | enum | Defines the KPI to track. Possible values: COUNT, GROSS_SALES, PURCHASE_AMOUNT, VISIT, TARGET_AMOUNT, TARGET_COUNT, TARGET_VISIT, EXTENDED_FIELD, EXTENDED_FIELD_PURCHASE_AMOUNT, TARGET_EXTENDED_FIELD_PURCHASE_AMOUNT, POINTS_BASED, MEMBER_SPEND. |
| ...targetEntity | enum | Specifies the entity to track against. Possible values: TRANSACTION, LINEITEM, POINTS, EVENT, ALTERNATE_CURRENCIES. |
| ...targetRuleMetaData | Object | Present when targetType is EXTENDED_FIELD. Defines which custom extended field is tracked and how its values are aggregated. |
| ....name | String | The name of the extended field being tracked. Example: "CentralGST" |
| ....aggregateFunction | String | The aggregation function applied to the extended field values. Possible values: SUM, COUNT, MAX, MIN. |
| ...defaultValue | string | Specifies the target value threshold. |
| ...targetValue | string | Specifies the target value to achieve. |
| ...preferredTillId | integer (int64) | Indicates a preferred till ID. |
| ...frequencyType | string | Specifies the frequency type for evaluation. |
| ...targetEvaluationType | enum | Specifies the evaluation logic window. Possible values: FIXED_CALENDAR_WINDOW, CYCLIC_WINDOW, PERIOD_AGNOSTIC_WINDOW, CALENDAR_CYCLIC_WINDOW. |
| ...recurringCycles | integer (int32) | Specifies the number of recurring cycles. |
| ...targetGroupId | integer (int64) | Indicates the target group ID. |
| ...leaderboardEnabled | boolean | Indicates if a leaderboard is enabled. |
| ...cycleActionMapping | Array (Object) | Specifies actions associated with milestone cycles. |
| ...streaks | Array (Object) | Defines streak configuration (StreakConfig). |
| ....name | string | Specifies the streak name. |
| ....targetCountOfSequence | integer (int32) | Specifies the required count to achieve the streak. |
| ....consecutive | boolean | Indicates if the sequence must be consecutive. |
| ...aggregateFunction | string | Specifies the function to aggregate values. |
| ...cycles | Array (Object) | Defines the evaluation cycles specific to this milestone. |
| ...periods | Array (Object) | Defines the periods for the milestone. |
| ...targetRuleIds | Array (integer int64) | Indicates associated target rule IDs. |
| ...individualMilestoneFileDetails | Array (Object) | Details related to uploaded files for individual targets. |
| ....uploadFileName | string | The original name of the uploaded file. |
| ....fileUrl | string | The system URL where the file is stored. |
| ....status | string | The processing status of the file. |
| ....totalRecords | integer | The total number of records found in the file. |
| ....successRecords | integer | The number of records successfully processed. |
| ....failureCount | integer | The number of records that failed to process. |
| ..allCycles | Array (Object) | Defines a list of all cycles. |
| ..combinationType | String | Indicates how child activities are combined. Possible values: ANY, ALL. |
| ..children | Array (Object) | Defines an array of child GroupActivity or SingleActivity objects. |
| .comments | String | Specifies any comments on the promotion. |
| .parentId | String | Specifies the ID of the parent promotion. |
| .parentDetails | Object | Defines details of the parent promotion. |
| ..id | String | Specifies the parent promotion ID. |
| ..status | String | Specifies the parent promotion status. |
| ..version | Integer (int32) | Specifies the parent promotion version. |
| ..lastModifiedBy | Integer (int32) | Specifies the user who last modified the parent. |
| ..lastModifiedOn | String (date-time) | Indicates when the parent promotion was last modified in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .version | Integer (int32) | Specifies the version number of the promotion. |
| .limits | Array (Object) | Defines a list of limits for the promotion (LimitResponse). |
| ..id | Integer (int64) | Specifies the limit ID (system-assigned). |
| ..entityScope | String | Indicates the scope of the limit. Possible values: PROMOTION, PROGRAM. |
| ..granularity | String | Indicates the granularity of the limit. Possible values: OVERALL, USER, PER_ACTIVITY. |
| ..entityId | Integer (int64) | Specifies the entity ID the limit applies to. |
| ..actionType | String | Indicates the action type being limited. Possible values: AWARD_CURRENCY, AWARD_BADGE, ISSUE_COUPON, ISSUE_REWARD, UPGRADE_TIER, RENEW_TIER, DOWNGRADE_TIER. |
| ..actionSubTypeId | String | Specifies the action sub-type ID. |
| ..limitType | String | Indicates the type of limit. Possible values: SUM, COUNT. |
| ..limitValue | Number | Specifies the value of the limit. |
| ..period | Object | Defines the time period for the limit. |
| ...id | Integer (int64) | Specifies the period ID. |
| ...periodType | String | Indicates the type of period. Possible values: FIXED_CALENDAR_WINDOW, NON_PERIOD_BASED, MOVING_WINDOW, CYCLIC_WINDOW. |
| ...periodUnit | String | Indicates the unit for the period. Possible values: DAYS, WEEKS, MONTHS. |
| ...periodValue | Integer (int32) | Specifies the value for the period. |
| ...periodStartDay | String | Indicates the start day for weekly periods. Possible values: MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY. |
| ...startDate | String (date-time) | Indicates the period's fixed start date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...endDate | String (date-time) | Indicates the period's fixed end date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..createdOn | String (date-time) | Indicates the limit's creation timestamp in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..createdBy | Integer (int64) | Specifies the user ID of the limit creator. |
| ..lastUpdatedOn | String (date-time) | Indicates the limit's last update timestamp in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ..lastUpdatedBy | Integer (int64) | Specifies the user ID of the last user who updated the limit. |
| ..active | Boolean | Indicates if the limit is active. |
| .liabilityOwnerSplitInfo | Array (Object) | Defines how liability is split. |
| ..orgId | Integer (int32) | Specifies the organization ID. |
| ..liabilityOwnerId | Integer (int32) | Specifies the liability owner ID. |
| ..componentId | Integer (int32) | Specifies the component ID. |
| ..componentType | String | Indicates the component type. Possible values: PROMOTION, PROGRAM. |
| ..createdBy | Integer (int32) | Specifies the user ID of the creator. |
| ..ratio | Number (double) | Specifies the liability split ratio. |
| ..liabilityOwnerName | String | Specifies the liability owner's name. |
| ..liabilityOwnerType | String | Indicates the liability owner's type. Possible values: PROGRAM, PARTNER. |
| ..active | Boolean | Indicates if the split info is active. |
| .workflowMetadata | Object | Defines workflow metadata for enrollment and opt-in. |
| ..enrolment | Object | Defines enrollment workflow details. |
| ...basedOn | String | Indicates the enrollment trigger type. Possible values: ACTIVITY, AUDIENCE, EXTERNAL_TRIGGER. |
| ...activities | Array (Object) | Defines activities triggering enrollment. |
| ...audienceMapping | Array (Object) | Defines audience mappings for enrollment. |
| ....groupId | Integer (int64) | Specifies the group ID. |
| ....groupName | String | Specifies the group name. |
| ...restrictions | Object | Defines enrollment restrictions. |
| ....optinExpiryBasedOn | Object | Defines opt-in expiry (PromotionExpiryConfigResponse). |
| .....value | Integer (int32) | Specifies the expiry value. |
| .....expiryDate | String (date-time) | Indicates the expiry date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .....type | String | Specifies the expiry type. |
| ....enrolmentExpiryBasedOn | Object | Defines enrollment expiry. |
| .....value | Integer (int32) | Specifies the expiry value. |
| .....expiryDate | String (date-time) | Indicates the expiry date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .....type | String | Specifies the expiry type. |
| ....optinLimitPerCustomer | Object | Defines opt-in limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....maxRedemptionsPerEarnPerCustomer | Object | Defines redemption limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....enrolmentLimitPerPromotion | Object | Defines total enrolment limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....enrolmentLimitPerCustomer | Object | Defines enrollment limit per customer . |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....maxPointsPerEarnPerCustomer | Object | Defines max points per earn limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ..optin | Object | Defines opt-in workflow details. |
| ...basedOn | String | Indicates the opt-in trigger type. Possible values: ACTIVITY, AUDIENCE, EXTERNAL_TRIGGER. |
| ...activities | Array (Object) | Defines activities triggering opt-in. |
| ...audienceMapping | Array (Object) | Defines audience mappings for opt-in. |
| ....groupId | Integer (int64) | Specifies the group ID. |
| ....groupName | String | Specifies the group name. |
| ...restrictions | Object | Defines opt-in restrictions. |
| ....optinExpiryBasedOn | Object | Defines opt-in expiry. |
| .....value | Integer (int32) | Specifies the expiry value. |
| .....expiryDate | String (date-time) | Indicates the expiry date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .....type | String | Specifies the expiry type. |
| ....enrolmentExpiryBasedOn | Object | Defines enrollment expiry. |
| .....value | Integer (int32) | Specifies the expiry value. |
| .....expiryDate | String (date-time) | Indicates the expiry date in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC) India server example: 2025-12-16T14:30:45+05:30 → 16 December 2025, 14:30:45 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .....type | String | Specifies the expiry type. |
| ....optinLimitPerCustomer | Object | Defines opt-in limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....maxRedemptionsPerEarnPerCustomer | Object | Defines redemption limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....enrolmentLimitPerPromotion | Object | Defines total enrollment limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....enrolmentLimitPerCustomer | Object | Defines enrollment limit per customer. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ....maxPointsPerEarnPerCustomer | Object | Defines max points per earn limit. |
| .....value | Integer (int32) | Specifies the limit value. |
| .....type | String | Specifies the limit period type. |
| .....periodType | String | Specifies the window type. |
| .....periodUnit | String | Specifies the period unit. |
| ...optInStartDate | String | Indicates the opt-in window start in ISO 8601 format, returned in the server time zone. EU server example: 2026-03-01T00:00:00Z → 01 March 2026, 00:00:00 (UTC) India server example: 2026-03-01T00:00:00+05:30 → 01 March 2026, 00:00:00 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| ...optInEndDate | String | Indicates the opt-in window end in ISO 8601 format, returned in the server time zone. EU server example: 2026-03-31T23:59:59Z → 31 March 2026, 23:59:59 (UTC) India server example: 2026-03-31T23:59:59+05:30 → 31 March 2026, 23:59:59 (IST) Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
| .communicationApprovalStatus | Object | Defines the status of communication approval. |
| ..success | Boolean | Indicates if the approval status check was successful. |
| ..message | String | Specifies the status message. |
| ..response | Object | Contains the details of the communication approval status check. |
| ..statusCode | Integer (int32) | Specifies the status code. |
| errors | Array (Object) | Defines a list of errors that occurred, if any. |
| .code | Integer (int64) | Specifies the error code. |
| .message | String | Specifies the error message. |
| warnings | Array (Object) | Defines a list of warnings, if any. |
| .message | String | Specifies the warning message. |
Error codes
| Code | Description |
|---|---|
| 300004 | Invalid input. Check request body format and required fields. |
| 300006 | Service operation failed. Check orchestration validation errors or service availability. |
| 310159 | Promotion identifier already exists. Use a unique promoIdentifier or ensure the existing promotion is in SNAPSHOT status. |
| 310177 | Promotion metadata key is required. Provide a non-empty key for each promotionMetadata entry. |
| 310178 | Promotion metadata value is required. Provide a non-empty value for each promotionMetadata entry. |
| 310179 | Duplicate promotion metadata key found. Ensure each key in promotionMetadata is unique. |
| 310180 | Promotion metadata key exceeds 100 characters. Reduce key length to 100 characters or less. |
| 310181 | Promotion metadata value exceeds 1000 characters. Reduce value length to 1000 characters or less. |
| 310182 | Promotion metadata isBrandDefined field must be 'true' or 'false'. Use only these values. |
| 310184 | AlwaysApply cannot be combined with stackable or exclusive. Set only one of these flags in loyaltyConfigMetaData. |
| 310185 | Promotion cannot be both stackable and exclusive. Set only one of these flags in loyaltyConfigMetaData. |
| 300006 | Opt-in duration fields are passed but this feature is not enabled for your org. Contact your org admin to enable the CONF_ENROLMENT_OPTIN_DURATION_ENABLED org flag. |
| 300006 | Opt-in duration is not applicable for this promotion configuration. Opt-in window is only supported when promotionType is LOYALTY_EARNING. |
| 300006 | Both optInStartDate and optInEndDate are required for opt-in window. Set both dates together or omit both. |
| 300006 | OptInStartDate must be before optInEndDate. Ensure the opt-in start date is earlier than the opt-in end date. |
| 300006 | OptInEndDate must be on or before promotion end date. Set optInEndDate to a date on or before the promotion endDate. |
| 400 | Request validation failed. Check required fields: name, startDate, endDate, promotionType, status, and activity blocks. |
| 500 | Internal server error. Retry the request or contact support if it persists. |
Example Overview
*Applying the metadata object to configure a promotion (StyleSavvy Boutique) *Applying the metadata object to configure a promotion (Generic Promo + ISSUE_AND_EARN) *Applying the customerEnrolment object to configure a promotion (Wellness Week) *Applying the customerEnrolment object to configure a promotion (Beta Tester)
- Creating a promotion with an opt-in window *Applying the activities object to configure a promotion (Workout Warrior) *Applying the activities object to configure a promotion (Dinner Special) *Applying the limits object to configure a promotion (Fresh Juice Bar) *Applying the limits object to configure a promotion (Global Gadgets) *FIXED_CALENDAR_WINDOW - every 5 days from reference date *FIXED_CALENDAR_WINDOW - every week starting Monday *FIXED_CALENDAR_WINDOW - every calendar month *Applying the liabilityOwnerSplitInfo object to configure a promotion (DocDemo split) *Applying the liabilityOwnerSplitInfo object to configure a promotion (Digital Hub standard) *Broadcast promotion — Immediate, Once (Award Currency)
- Broadcast promotion — Specific date, Daily (Award Badge)
delegateActionClass Values
The delegateActionClass field inside mandatoryPropertiesValues specifies the Java implementation class for the action. The value must correspond to the actionName set on the action object.
| Action | actionName | delegateActionClass |
|---|---|---|
| Advance Currency Allocation | ADVANCE_CURRENCY_ALLOCATION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl |
| Allocate Points | AWARD_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl |
| Allocate Target Points | AWARD_TARGET_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardTargetPointsActionImpl |
| Award Referrer Points | AWARD_REFERRER_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardReferrerPointsActionImpl |
| Award Referee Points | AWARD_REFEREE_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardRefereePointsActionImpl |
| Badge Earn | BADGE_EARN_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.BadgeEarnActionImpl |
| Bill Points Allocation | BILL_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.BillAwardPointsActionImpl |
| Convert Points to Reward | CONVERT_POINTS_TO_REWARD_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.RewardIssualActionImpl |
| Customer Status Update | STATUS_LABEL_UPDATE_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.StatusLabelUpdateActionImpl |
| Delayed Accrual | DELAYED_ACCRUAL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.DelayedAccrualActionImpl |
| Earn Promotion | EARN_PROMOTION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.EarnPromotionActionImpl |
| Forward Action | FORWARD | com.capillary.shopbook.nrules.impl.action.ForwardAction |
| Initiate Supplementary Membership | INITIATE_SUPPLEMENTARY_MEMBERSHIP | com.capillary.shopbook.pointsengine.endpoint.impl.action.TransactionPartnerProgramLinkingActionImpl |
| Issue a Voucher | PE_ISSUE_VOUCHER_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineIssueVoucherActionImpl |
| Issue Promotion | ISSUE_PROMOTION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.IssuePromotionActionImpl |
| Points Contribution to Group | POINTS_CONTRIBUTION_TO_GROUP_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsContributionToGroupActionImpl |
| Points Group Redemption | POINTS_GROUP_REDEMPTION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsGroupRedemptionActionImpl |
| Points Group Transfer | POINTS_GROUP_TRANSFER_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsGroupTransferActionImpl |
| Points Redemption Reversal | POINTS_REDEMPTION_REVERSAL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsRedemptionReversalActionImpl |
| Points Transfer | POINTS_TRANSFER_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsTransferActionImpl |
| Re-evaluate Regular Bill | REEVALUATE_REGULAR_BILL | com.capillary.shopbook.pointsengine.endpoint.impl.action.ReevaluateRegularBillActionImpl |
| Redeem Points | REDEEM_POINTS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.RedeemPointsActionImpl |
| Renew Slab | RENEW_SLAB_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeSlabActionImpl |
| Renew Tier Based on Partner Program | RENEW_TIER_BASED_ON_PARTNER_PROGRAM | com.capillary.shopbook.pointsengine.endpoint.impl.action.RenewTierBasedOnPartnerProgramActionImpl |
| Return Bill | RETURN_BILL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.ReturnBillActionImpl |
| Send Communication | SEND_COMMUNICATION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineSendCommunicationActionImpl |
| Send E-Bill | EBILL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.EBillActionImpl |
| Send Email | PE_EMAIL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineEmailActionImpl |
| Send Facebook Message | PE_FACEBOOK_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineFacebookMessageActionImpl |
| Send Messages Template | PE_MESSAGE_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineMessageActionImpl |
| Send Mobile Push | PE_MOBILE_PUSH_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineMobilePushActionImpl |
| Send SMS | PE_SMS_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineSmsActionImpl |
| Send WeChat Message | PE_WECHAT_MESSAGE_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineWeChatActionImpl |
| Tag Customer | TAG_CUSTOMER_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.TagCustomerActionImpl |
| Tier Action V2 | TIER_ACTION_V2 | com.capillary.shopbook.pointsengine.endpoint.impl.action.TierActionImpl |
| Tracker Evaluation | TRACKER_EVALUATION_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.TrackerEvaluationActionImpl |
| Trigger Based Delayed Accrual | TRIGGER_BASED_DELAYED_ACCRUAL_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.TriggerBasedDelayedAccrualActionImpl |
| Upgrade Slab | UPGRADE_SLAB_ACTION | com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeSlabActionImpl |
| Upgrade Slab (Slab Specific) | UPGRADE_SLAB_ACTION_SLAB | com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeSlabActionImpl |
| Upgrade Slab (Strategy Specific) | UPGRADE_SLAB_ACTION_STRATEGY | com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeSlabActionImpl |
| Upgrade Tier Based on Partner Program | UPGRADE_TIER_BASED_ON_PARTNER_PROGRAM | com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeTierBasedOnPartnerProgramActionImpl |
Detailed Examples
Applying the metadata object to configure a promotion (StyleSavvy Boutique) : [metadata Object]
Requirement: StyleSavvy Boutique has configured a promotion named "StyleSavvy VIP Early Access-lock," active from November 10th to November 15th, 2025. This promotion is tagged internally as "Access: VIP" and "Event: EarlyBird". The condition is: if any customer makes a transaction during this period, the system will automatically apply this promotion. The promotion itself cannot be stacked or combined with other offers. The primary action triggered is the awarding of points. Still, these points will not count towards the customer's tier ranking, and they will follow the standard earning rules (meaning they cannot be redeemed immediately).
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNhMjI2MTk1AxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=v6fczCvRgra_Nl09ZghriPj6qgpGIWfxeg-1763147102119-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "StyleSavvy VIP Early Access-lock",
"description": "VIP early access promotion for StyleSavvy customers. Awards points on any transaction between Nov 10–15, 2025. Points do not count towards tier ranking.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-11-10T00:00:00+05:30",
"endDate": "2025-11-15T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "stylesavvy-vip-early-access",
"promotionMetadata":[
{"key": "Access", "value": "VIP"},
{"key": "Event", "value": "EarlyBird"}
]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_1761xxxxxxb1",
"type": "SINGLE",
"name": "Award Points",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-11-10T00:00:00+05:30",
"endDate": "2025-11-15T23:59:59+05:30",
"actions":[
{
"id": "temp_action_pts_split",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award Points with 100% Liability",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109436",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits": [],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the metadata object to configure a promotion (Generic Promo + ISSUE_AND_EARN) : [metadata Object]
Requirement: Generic Promo + ISSUE_AND_EARN: Adventure Quest Outfitters has set up a promotion called the "Gear Up Challenge," running from December 1st to December 31st. This promotion is configured as a "Generic" type, meaning its reward might be something other than standard loyalty points, like a digital badge. The key condition is how rewards are given: when a customer qualifies, the reward is first issued (like receiving a pending notification or item), but it isn't fully earned or usable until potentially later, perhaps after meeting another condition or after a delay. This promotion follows standard interaction rules, meaning it won't automatically combine with other offers or block them unless specifically configured elsewhere. The main action triggered is the awarding of a badge.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=T9hxqIAAnGjc8UEdEpq7PXhCTJbHD_w-1763195859760-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Gear Up Challenge",
"description": "Generic promo for Gear Up Challenge. Issue and Earn.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "GENERIC",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "gear-up-challenge",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_1761xxxxxx02",
"type": "SINGLE",
"name": "Challenge Activity",
"event": "CustomEvent",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_badge",
"actionName": "AWARD_BADGE",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardBadgeActionImpl",
"description": "Award Gear Up Badge",
"mandatoryPropertiesValues": {
"badgeId": "GEAR_UP_DEC25"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones": []
}
],
"limits":[],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the customerEnrolment object to configure a promotion (Wellness Week) :[customerEnrolment Object]
Requirement: Healthy Habits Cafe is running a "Wellness Week Opt-In" promotion from November 17th to 23rd, but only for a specific group of pre-selected customers. To participate, these customers must first "opt-in" by making any purchase during that week. After they have opted-in, the reward is earning 100 points on their future purchases. The promotion has several limits, such as capping the total number of customers who can opt-in at 500 and limiting the points earned from a single activity to 200.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW862MTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=LpG9HQ0MrgtUJNTMOdr1nbz8FvnCc-1763223314046-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Wellness Week Opt-In",
"description": "Audience enroll, activity opt-in w/ ALL restrictions.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-11-17T00:00:00+05:30",
"endDate": "2025-11-23T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "wellness-week-opt-in",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "AUDIENCE_FILTER",
"audienceGroups":[
{
"audienceGroupId": 612174375,
"audienceGroupName": "Pre-selected Wellness Group",
"description": "Pre-selected customer list"
}
]
},
"workflowMetadata": {
"optin": {
"basedOn": "ACTIVITY",
"activities":[
{
"id": "activity_1761xxxxxx03",
"type": "SINGLE",
"name": "Opt-in via Purchase",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-11-17T00:00:00+05:30",
"endDate": "2025-11-23T23:59:59+05:30",
"actions":[
{
"id": "temp_action_optin_aaa",
"actionName": "EARN_PROMOTION_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.EarnPromotionActionImpl",
"description": "Perform Opt-In",
"mandatoryPropertiesValues": {
"promotionIdentifier": "wellness-week-opt-in",
"activityName": "Opt-in via Purchase",
"delegateActionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.EarnPromotionActionImpl"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"audienceMapping":[],
"restrictions": {
"optinExpiryBasedOn": {
"type": "PROMOTION",
"value": ""
},
"enrolmentExpiryBasedOn": {
"type": "CUSTOM",
"value": 30
},
"optinLimitPerCustomer": {
"value": "1",
"type": "PERIOD_BASED",
"periodType": "MOVING_WINDOW",
"periodUnit": "DAILY"
},
"maxRedemptionsPerEarnPerCustomer": {
"value": "5",
"type": "NON_PERIOD_BASED"
},
"enrolmentLimitPerPromotion": {
"value": "500"
},
"enrolmentLimitPerCustomer": {
"value": "1"
},
"maxPointsPerEarnPerCustomer": {
"value": 200,
"type": "NON_PERIOD_BASED"
}
}
},
"enrolment": {}
},
"activities":[
{
"id": "activity_1761xxxxxx04",
"type": "SINGLE",
"name": "Wellness Reward",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-11-17T00:00:00+05:30",
"endDate": "2025-11-23T23:59:59+05:30",
"actions":[
{
"id": "temp_action_wellness",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award 100 Wellness Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109436",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones": []
}
],
"limits": [],
"liabilityOwnerSplitInfo":[]
}'Applying the customerEnrolment object to configure a promotion (Beta Tester) : [customerEnrolment Object]
Requirement: Gadget Galaxy is running a "Beta Tester Program" for the first quarter of the year. A specific list of customers is manually enrolled into this program. Additionally, any customer who joins the "PreOrder List" (a specific audience group) is automatically enrolled as well. Once enrolled, these members can earn a reward: when they perform the "FeedbackSubmitted" action, they will receive 100 points. This promotion has several restrictions, such as limiting automatic enrollment to 1,000 customers total and capping the points earned from a single activity at 500.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1Tk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=LpG9HQ0MrgtUJNTMOdr1nbz8FvnCc-1763223314046-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Beta Tester Program",
"description": "Import enroll, audience dynamic enroll. Point cap in main limits.",
"orgId": 100737,
"programId": 973,
"startDate": "2026-01-01T00:00:00+05:30",
"endDate": "2026-03-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "beta-tester-program",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "IMPORT",
"audienceGroups":[]
},
"workflowMetadata": {
"optin": {},
"enrolment": {
"basedOn": "AUDIENCE",
"activities":[],
"audienceMapping":[
{
"groupId": 612174375,
"groupName": "PreOrder List"
}
],
"restrictions": {
"enrolmentLimitPerPromotion": {
"value": "1000"
}
}
}
},
"activities":[
{
"id": "activity_1761xxxxxx05",
"type": "SINGLE",
"name": "Beta Reward (100 Points)",
"event": "FeedbackSubmitted",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2026-01-01T00:00:00+05:30",
"endDate": "2026-03-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_beta_pts",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award 100 Beta Tester Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109006",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits":[
{
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 500,
"period": {
"periodType": "NON_PERIOD_BASED"
}
}
],
"liabilityOwnerSplitInfo":[]
}'Creating a promotion with an opt-in window : [workflowMetadata Object]
Requirement: WellnessFirst is running a "Spring Health Challenge" during March 2026. To control participation, the opt-in window opens on February 15th — customers must opt in via an external API call before the promotion ends on March 31st. After opting in, they earn points on qualifying purchases throughout March. This requires the CONF_ENROLMENT_OPTIN_DURATION_ENABLED feature flag to be enabled for the org.
CONF_ENROLMENT_OPTIN_DURATION_ENABLED feature flag to be enabled for the org.curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <your_credentials>' \
--data '{
"metadata": {
"name": "Spring Health Challenge",
"description": "Spring Health Challenge",
"programId": 2849,
"startDate": "2026-03-01T00:00:00+05:30",
"endDate": "2026-03-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "PENDING_APPROVAL",
"promoIdentifier": "SPRING_HEALTH_CHALLENGE_MAR26",
"timezoneName": "Asia/Kolkata",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "IMPORT",
"audienceGroups":[],
"customerEligibilityType": "ALL"
},
"liabilityOwnerSplitInfo": [],
"activities":[
{
"id": "2e94e0e0-fd12-4912-997f-9483ed69e0e0",
"name": "Activity 1",
"type": "SINGLE",
"event": "TransactionAdd",
"milestones": [],
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2026-03-01T00:00:00+05:30",
"endDate": "2026-03-31T23:59:59+05:30",
"actions": []
}
],
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}"
}
],
"workflowMetadata": {
"optin": {
"basedOn": "EXTERNAL_TRIGGER",
"optInStartDate": "2026-02-15T00:00:00+05:30",
"optInEndDate": "2026-03-31T23:59:59+05:30",
"restrictions": {
"optinExpiryBasedOn": {
"type": "PROMOTION",
"value": ""
},
"optinLimitPerCustomer": {
"value": "1"
}
}
},
"enrolment": {
"basedOn": "EXTERNAL_TRIGGER",
"restrictions": {
"enrolmentExpiryBasedOn": {
"type": "PROMOTION",
"value": 0
},
"enrolmentLimitPerCustomer": {
"value": "1"
},
"maxRedemptionsPerEarnPerCustomer": {
"value": "1",
"type": "NON_PERIOD_BASED"
}
}
}
}
}'Applying the activities object to configure a promotion (Workout Warrior) : [activities Object]
Requirement: FitNation Gym is running a "Workout Warrior" challenge for all of November, but it only counts visits at their Location 101 gym. The system will count every check-in event at that specific location, tracking progress week by week. A leaderboard will be active so members can compete and see who is checking in the most. The main goal for customers is to complete 15 separate check-ins at Location 101 before the end of the month. As soon as a member hits their 15th visit, they win the challenge and are automatically upgraded to Tier 2 in the gym's loyalty program.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic <your_credentials>' \
--data '{
"metadata": {
"name": "Workout Warrior",
"description": "Milestone: 15 Gym Check-ins in Nov at Loc 101. Reward: Tier Upgrade.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-11-01T00:00:00+05:30",
"endDate": "2025-11-30T23:59:59+05:30",
"promotionType": "GENERIC",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "workout-warrior",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_1761000000006",
"type": "SINGLE",
"name": "Track Gym CheckIns",
"event": "GymCheckIn",
"expJSON": "{\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"==\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"number:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"event:object:primitive\",\n \"value\": \"currentEvent\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"number:object:primitive\",\n \"value\": \"locationId\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"number:primitive\",\n \"value\": \"101\"\n }\n ]\n}",
"commonCycleActionMapping":[],
"activityCycles":[
{
"id": "ac_w1",
"name": "Nov Week 1",
"startDate": "2025-11-01T00:00:00+05:30",
"endDate": "2025-11-09T23:59:59+05:30",
"refCode": "W1",
"isActive": true
},
{
"id": "ac_w2",
"name": "Nov Week 2",
"startDate": "2025-11-10T00:00:00+05:30",
"endDate": "2025-11-16T23:59:59+05:30",
"refCode": "W2",
"isActive": true
},
{
"id": "ac_w3",
"name": "Nov Week 3",
"startDate": "2025-11-17T00:00:00+05:30",
"endDate": "2025-11-23T23:59:59+05:30",
"refCode": "W3",
"isActive": true
},
{
"id": "ac_w4",
"name": "Nov Week 4",
"startDate": "2025-11-24T00:00:00+05:30",
"endDate": "2025-11-30T23:59:59+05:30",
"refCode": "W4",
"isActive": true
}
],
"milestones":[
{
"name": "Achieve 15 Check-Ins",
"trackingType": "DEFAULT",
"frequencyType": "WEEKLY",
"targetEvaluationType": "CYCLIC_WINDOW",
"recurringCycles": 4,
"leaderboardEnabled": true,
"targetType": "COUNT",
"targetEntity": "EVENT",
"aggregateFunction": "COUNT",
"preferredTillId": null,
"cycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-11-01T00:00:00+05:30",
"endDate": "2025-11-30T23:59:59+05:30",
"defaultValue": "15",
"actions":[
{
"id": "temp_action_tierup",
"actionName": "UPGRADE_SLAB_ACTION_SLAB",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.UpgradeSlabActionImpl",
"description": "Upgrade to Tier 2",
"mandatoryComplexPropertiesValues": {},
"mandatoryPropertiesValues": {
"EvaluatedEntity": "USER",
"ToSlabSerialNumber": "2",
"TierBasedExpiry": "0"
},
"embeddedStrategies": []
}
]
}
]
}
]
}
],
"limits": [],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the activities object to configure a promotion (Dinner Special) :[activities Object]
Requirement: Gourmet Galaxy Foods has a "Dinner Special" promotion that awards points, but it's only active during specific dinner hours. To get the points, a customer must meet one of two conditions: they can either just buy a 'Premium Steak', OR they must buy an 'Organic Salad', an 'Artisan Bread', and have their total transaction be over $30, all in the same purchase. The system uses special internal rules (rulesets) to validate this bundle and to apply the reward only during the specified dinner-hour cycle.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNhMZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=LpG9HQ0MrgpPTMOdr1nbz8FvnCc-1763223314046-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Dinner Special",
"description": "Points for Steak OR (Salad AND Bread AND >$30), dinner hours only.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-11-01T00:00:00+05:30",
"endDate": "2025-11-30T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "dinner-special",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups":[]
},
"activities":[
{
"id": "group_176100000007",
"type": "GROUP",
"name": "Dinner Special Check (ANY)",
"combinationType": "ANY",
"cycles":[
{
"id": "c_dinner",
"name": "Dinner Hours",
"startDate": "2025-11-01T18:00:00+05:30",
"endDate": "2025-11-30T22:00:00+05:30"
}
],
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"children":[
{
"id": "sub_activity_176100000008",
"parentId": "group_176100000007",
"name": "Bought Premium Steak",
"type": "SINGLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"unary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"exists\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"collection:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"transaction:object:primitive\",\n \"value\": \"currentTransaction\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"collection:object:primitive\",\n \"value\": \"lineItems\"\n }\n ]\n },\n {\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"==\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"string:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"item:object:primitive\",\n \"value\": \"item\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"string:object:primitive\",\n \"value\": \"sku\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"string:primitive\",\n \"value\": \"GG-STK-01\"\n }\n ]\n }\n ]\n}",
"milestones":[
{
"name": "Default Milestone Steak",
"trackingType": "DEFAULT",
"leaderboardEnabled": false
}
],
"commonCycleActionMapping":[]
},
{
"id": "sub_group_176100000009",
"parentId": "group_176100000007",
"name": "Side Bundle Check (ALL)",
"type": "GROUP",
"combinationType": "ALL",
"rulesetId": "SIDE_BUNDLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"children":[
{
"id": "sub_sub_activity_10",
"parentId": "sub_group_176100000009",
"name": "Bought Organic Salad",
"type": "SINGLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"unary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"exists\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"collection:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"transaction:object:primitive\",\n \"value\": \"currentTransaction\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"collection:object:primitive\",\n \"value\": \"lineItems\"\n }\n ]\n },\n {\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"==\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"string:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"item:object:primitive\",\n \"value\": \"item\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"string:object:primitive\",\n \"value\": \"sku\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"string:primitive\",\n \"value\": \"GG-SAL-01\"\n }\n ]\n }\n ]\n}",
"milestones":[
{
"name": "Default Milestone Salad",
"trackingType": "DEFAULT",
"leaderboardEnabled": false
}
],
"commonCycleActionMapping":[]
},
{
"id": "sub_sub_activity_11",
"parentId": "sub_group_176100000009",
"name": "Bought Artisan Bread",
"type": "SINGLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"unary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"exists\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"collection:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"transaction:object:primitive\",\n \"value\": \"currentTransaction\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"collection:object:primitive\",\n \"value\": \"lineItems\"\n }\n ]\n },\n {\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \"==\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"string:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"item:object:primitive\",\n \"value\": \"item\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"string:object:primitive\",\n \"value\": \"sku\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"string:primitive\",\n \"value\": \"GG-BRD-01\"\n }\n ]\n }\n ]\n}",
"milestones":[
{
"name": "Default Milestone Bread",
"trackingType": "DEFAULT",
"leaderboardEnabled": false
}
],
"commonCycleActionMapping":[]
},
{
"id": "sub_sub_activity_12",
"parentId": "sub_group_176100000009",
"name": "Transaction > $30",
"type": "SINGLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"binary_operation\",\n \"type\": \"boolean:primitive\",\n \"value\": \">\",\n \"operands\":[\n {\n \"arity\": \"object_dereference\",\n \"type\": \"real:object:primitive\",\n \"operands\":[\n {\n \"arity\": \"name\",\n \"type\": \"transaction:object:primitive\",\n \"value\": \"currentTransaction\"\n },\n {\n \"arity\": \"name\",\n \"type\": \"real:object:primitive\",\n \"value\": \"amount\"\n }\n ]\n },\n {\n \"arity\": \"literal\",\n \"type\": \"number:primitive\",\n \"value\": \"30\"\n }\n ]\n}",
"milestones":[
{
"name": "Default Milestone Amount",
"trackingType": "DEFAULT",
"leaderboardEnabled": false
}
],
"commonCycleActionMapping":[]
}
],
"commonCycleActionMapping":[]
}
],
"commonCycleActionMapping":[
{
"cycle": "c_dinner",
"startDate": "2025-11-01T18:00:00+05:30",
"endDate": "2025-11-30T22:00:00+05:30",
"rulesetId": "DINNER_REWARD_RULES",
"actions":[
{
"id": "temp_action_dinnerpts",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award 150 Dinner Special Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "111728",
"ExpiryStrategy": "121544",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
]
}
],
"limits":[],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the limits object to configure a promotion (Fresh Juice Bar) :[limits Object]
Requirement: Fresh Juice Bar has configured a promotion for their B5G1_JUICE coupon. To manage its distribution, they have set a rule limiting how many coupons a single customer can earn: each customer is limited to receiving a maximum of 2 coupons. This limit resets every calendar week, which the brand has defined as starting on a Sunday.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTN2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=BC9cwq9xQ4RRIGlUxLEwV1ldTNVbpH1faK4-1763285329155-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Fresh Juice Weekly Coupon Limit",
"description": "Limit B5G1_JUICE coupon to 2 per user per calendar week, starting Sunday.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "GENERIC",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "fresh-juice-weekly-coupon-limit",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups":[]
},
"activities":[
{
"id": "activity_1761xxxxxxa1",
"type": "SINGLE",
"name": "Issue B5G1 Coupon",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_b5g1",
"actionName": "PE_ISSUE_VOUCHER_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineIssueVoucherActionImpl",
"description": "Issue B5G1 Juice Voucher",
"mandatoryPropertiesValues": {
"VoucherSeriesId": "B5G1_JUICE"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits":[
{
"granularity": "USER",
"actionType": "ISSUE_COUPON",
"actionSubTypeId": "B5G1_JUICE",
"limitType": "COUNT",
"limitValue": 2,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "WEEKS",
"periodValue": 1,
"periodStartDay": "SUNDAY"
}
}
],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the limits object to configure a promotion (Global Gadgets) : [limits Object]
Requirement: Global Gadgets runs a loyalty promotion awarding points on every purchase from February to April 2026. To protect total liability, the promotion caps the total points awarded across all customers at 1,000,000 in any rolling 30-day window.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=BC9cwq9u_qIzIGlUxLEwV1ldTNVbpH1faK4-1763285329155-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Global Gadgets Points Promotion",
"description": "Global Gadgets runs a loyalty promotion awarding points on every purchase from February to April 2026. To protect total liability, the promotion caps the total points awarded across all customers at 1,000,000 in any rolling 30-day window.",
"orgId": 100737,
"programId": 973,
"startDate": "2026-02-01T00:00:00+05:30",
"endDate": "2026-04-30T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "global-gadgets-points-promotion",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_1761xxxxxxa2",
"type": "SINGLE",
"name": "Award Points",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2026-02-01T00:00:00+05:30",
"endDate": "2026-04-30T23:59:59+05:30",
"actions":[
{
"id": "temp_action_pts_lim",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award Standard Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109006",
"PointType": "Points"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits":[
{
"entityScope": "PROMOTION",
"granularity": "OVERALL",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 1000000,
"period": {
"periodType": "MOVING_WINDOW",
"periodValue": 30,
"periodUnit": "DAYS"
}
}
],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'FIXED_CALENDAR_WINDOW - every 5 days from reference date : [period Object]
Requirement: TechRetail runs a year-long loyalty promotion awarding points on every purchase. To prevent over-earning, each customer is capped at 100 points per 5-day period, with periods anchored from January 1, 2025.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=<your_cookie>' \
--data '{
"metadata": {
"name": "Every 5 Days Points Limit",
"description": "TechRetail runs a year-long loyalty promotion awarding points on every purchase. To prevent over-earning, each customer is capped at 100 points per 5-day period, with periods anchored from January 1, 2025.",
"orgId": 100737,
"programId": 2607,
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "techretail-5day-points-limit",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups":[]
},
"activities":[
{
"id": "activity_001",
"type": "SINGLE",
"name": "Purchase Activity",
"event": "TransactionAdd",
"expJSON": "{\"arity\":\"literal\",\"type\":\"boolean:primitive\",\"value\":\"true\"}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_pts",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109006",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits":[
{
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 100,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "DAYS",
"periodValue": 5,
"referenceDate": "2025-01-01T00:00:00Z"
}
}
],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'FIXED_CALENDAR_WINDOW - every week starting Monday : [period Object]
Requirement: FashionHub runs a year-long promotion issuing free shipping coupons on every purchase. To control distribution, each customer is limited to 3 coupon redemptions per week, with each week starting on Monday.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=<your_cookie>' \
--data '{
"metadata": {
"name": "Weekly Coupon Limit",
"description": "FashionHub runs a year-long promotion issuing free shipping coupons on every purchase. To control distribution, each customer is limited to 3 coupon redemptions per week, with each week starting on Monday.",
"orgId": 100737,
"programId": 2607,
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "GENERIC",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "fashionhub-weekly-coupon-limit",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_002",
"type": "SINGLE",
"name": "Purchase Activity",
"event": "TransactionAdd",
"expJSON": "{\"arity\":\"literal\",\"type\":\"boolean:primitive\",\"value\":\"true\"}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_coupon",
"actionName": "PE_ISSUE_VOUCHER_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.PointsEngineIssueVoucherActionImpl",
"description": "Issue Free Shipping Coupon",
"mandatoryPropertiesValues": {
"VoucherSeriesId": "FREESHIP"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones":[]
}
],
"limits":[
{
"granularity": "USER",
"actionType": "ISSUE_COUPON",
"actionSubTypeId": "FREESHIP",
"limitType": "COUNT",
"limitValue": 3,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "WEEKS",
"periodValue": 1,
"periodStartDay": "MONDAY"
}
}
],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'FIXED_CALENDAR_WINDOW - every calendar month : [period Object]
Requirement: GroceryMart runs a year-long loyalty promotion awarding points on every purchase. To manage monthly earning potential, each customer is capped at 500 points per calendar month.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=<your_cookie>' \
--data '{
"metadata": {
"name": "Monthly Points Limit",
"description": "GroceryMart runs a year-long loyalty promotion awarding points on every purchase. To manage monthly earning potential, each customer is capped at 500 points per calendar month.",
"orgId": 100737,
"programId": 2607,
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "grocerymart-monthly-points-limit",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_003",
"type": "SINGLE",
"name": "Purchase Activity",
"event": "TransactionAdd",
"expJSON": "{\"arity\":\"literal\",\"type\":\"boolean:primitive\",\"value\":\"true\"}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-01-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_pts",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "Award Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109006",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones": []
}
],
"limits":[
{
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 500,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "MONTHS",
"periodValue": 1
}
}
],
"liabilityOwnerSplitInfo":[],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the liabilityOwnerSplitInfo object to configure a promotion (DocDemo split) : [liabilityOwnerSplitInfo Object]
Requirement: The brand has set up a promotion where the cost (liability) associated with the points awarded needs to be shared. The condition is: for any points given out by this promotion, the cost will be split equally (50/50) between two internal loyalty programs, specifically the "DocDemoDefaultProgram" and the "DocTransferPoints" program. This cost-sharing rule is active.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTNhMjI2MTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=BC9cwq9xQ4RRsN9u_qIzIGlUxLEwV1ldTNVbpH1faK4-1763285329155-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Liability Split - DocDemo and DocTransfer",
"description": "Split liability 50/50 between DocDemoDefaultProgram (82) and DocTransferPoints (87).",
"orgId": 100737,
"programId": 973,
"startDate": "2025-11-20T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "LOYALTY_EARNING",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "liability-split-docdemo-doctransfer",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups":[]
},
"activities":[
{
"id": "activity_1761xxxxxxb1",
"type": "SINGLE",
"name": "Award Points",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-11-20T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions":[
{
"id": "temp_action_pts_split",
"actionName": "AWARD_POINTS_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
"description": "100 Points",
"mandatoryPropertiesValues": {
"AwardStrategy": "109010",
"ExpiryStrategy": "109436",
"PointType": "Main"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies": []
}
]
}
],
"milestones": []
}
],
"limits": [],
"liabilityOwnerSplitInfo":[
{
"liabilityOwnerId": 82,
"componentType": "PROMOTION",
"ratio": 50,
"active": true,
"liabilityOwnerName": "DocDemoDefaultProgram",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
},
{
"liabilityOwnerId": 87,
"componentType": "PROMOTION",
"ratio": 50,
"active": true,
"liabilityOwnerName": "DocTransferPoints",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
}
],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Applying the liabilityOwnerSplitInfo object to configure a promotion (Digital Hub standard) : [liabilityOwnerSplitInfo Object]
Requirement: Digital Hub has set up a standard promotion linked to their main loyalty program (Org 100737, Prog 2607). For any rewards issued by this promotion, the configuration explicitly states: the full 100% of the cost (liability) is assigned solely to the main loyalty program (ID 2607). This setup confirms the default scenario where the program itself covers all expenses for the rewards given.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'content-type: application/json' \
--header 'Authorization: Basic Z2VvcmdlLmRvY2RlbW86MmQ1OTMTk1OGE2NWI5ZjAxMzU5NGIwNDllZTk=' \
--header 'Cookie: _cfuvid=BC9RRsN9u_qIzIGlUxLEwV1ldTNVbpH1faK4-1763285329155-0.0.1.1-604800000' \
--data '{
"metadata": {
"name": "Digital Hub Standard 100 Liability",
"description": "Standard promotion, 100% program liability to program 973.",
"orgId": 100737,
"programId": 973,
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"promotionType": "GENERIC",
"status": "DRAFT",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "digital-hub-standard-liability",
"promotionMetadata":[]
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION",
"audienceGroups": []
},
"activities":[
{
"id": "activity_1763288000001",
"name": "Activity 1",
"type": "SINGLE",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2025-12-01T00:00:00+05:30",
"endDate": "2025-12-31T23:59:59+05:30",
"actions": []
}
],
"milestones":[]
}
],
"limits": [],
"liabilityOwnerSplitInfo":[
{
"liabilityOwnerId": 82,
"componentType": "PROMOTION",
"ratio": 100,
"active": true,
"liabilityOwnerName": "DocDemoDefaultProgram",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
}
],
"workflowMetadata": {
"optin": {},
"enrolment": {}
}
}'Broadcast promotion — Immediate, Once (Award Currency)
A broadcast promotion that issues 500 points to all customers in two audience groups immediately after the promotion is approved. The reward is issued once.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <token>' \
--data '{
"metadata": {
"name": "VIP Summer Reward",
"description": "Reward VIP customers with 500 points",
"promotionType": "LOYALTY",
"promotionCategory": "BROADCAST",
"programId": "973",
"orgId": 51174,
"status": "DRAFT",
"startDate": "2026-06-01T00:00:00+05:30",
"endDate": "2026-06-30T23:59:59+05:30",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "vip-summer-reward-june",
"promotionMetadata":[]
},
"customerEnrolment": { "enrolmentMethod": "IMPORT" },
"liabilityOwnerSplitInfo":[
{
"liabilityOwnerId": 82,
"componentType": "PROMOTION",
"ratio": 100,
"active": true,
"liabilityOwnerName": "DocDemoDefaultProgram",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
}
],
"broadcastMetadata": {
"source": "AUDIENCE_FILTER",
"audienceFilter": {
"audienceListIds": [1130180]
},
"tillId": "75216507"
},
"activities":[
{
"id": "activity_broadcast_1",
"name": "Award 500 Points",
"type": "SINGLE",
"event": "BulkEMFEvent",
"milestones": [],
"expJSON": "{\"arity\":\"literal\",\"type\":\"boolean:primitive\",\"value\":\"true\"}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2026-06-01T00:00:00+05:30",
"endDate": "2026-06-30T23:59:59+05:30",
"actions":[
{
"id": "temp_action_points_1",
"actionName": "ADVANCE_CURRENCY_ALLOCATION_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl",
"description": "Award 500 points",
"mandatoryPropertiesValues": {
"PointType": "Main",
"Currency": "POINTS",
"EvaluatedEntity": "USER",
"delegateActionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies":[
{
"strategyTypeId": 1,
"propertyValues": "{\"allocation_type\":\"FIXED\",\"allocation_values\":\"500,500,500,500,500,500,500,500\"}",
"owner": "LOYALTY",
"updatedViaNewUI": true
},
{
"strategyTypeId": 3,
"propertyValues": "{\"expiry_type\":\"SLAB_INDEPENDENT\",\"expiry_from\":\"CURRENT_DATE\",\"expiry_time_units\":\"NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER\"}",
"owner": "LOYALTY",
"updatedViaNewUI": true
}
]
}
]
}
]
}
],
"promotionSchedule": {
"schedule": {
"startType": "IMMEDIATE",
"frequency": "ONCE"
}
}
}'Broadcast promotion — Specific date, Daily (Award Badge)
A broadcast promotion that awards a badge to all customers in an audience group daily, starting on a specific date and continuing until the promotion end date.
curl --location 'https://eu.api.capillarytech.com/v3/promotions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <token>' \
--data '{
"metadata": {
"name": "Daily Loyalty Badge — June 2026",
"description": "Award a daily loyalty badge to VIP audience",
"promotionType": "LOYALTY",
"promotionCategory": "BROADCAST",
"programId": "973",
"orgId": 51174,
"status": "DRAFT",
"startDate": "2026-06-01T00:00:00+05:30",
"endDate": "2026-06-30T23:59:59+05:30",
"timezoneName": "Asia/Kolkata",
"promoIdentifier": "daily-badge-june-2026",
"promotionMetadata":[]
},
"customerEnrolment": { "enrolmentMethod": "IMPORT" },
"liabilityOwnerSplitInfo":[
{
"liabilityOwnerId": 82,
"componentType": "PROMOTION",
"ratio": 100,
"active": true,
"liabilityOwnerName": "DocDemoDefaultProgram",
"liabilityOwnerType": "PROGRAM",
"orgId": 100737
}
],
"broadcastMetadata": {
"source": "AUDIENCE_FILTER",
"audienceFilter": {
"audienceListIds": [1130180]
},
"tillId": "75216507"
},
"activities":[
{
"id": "activity_broadcast_badge",
"name": "Award Daily Badge",
"type": "SINGLE",
"event": "BulkEMFEvent",
"milestones": [],
"expJSON": "{\"arity\":\"literal\",\"type\":\"boolean:primitive\",\"value\":\"true\"}",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"startDate": "2026-06-01T00:00:00+05:30",
"endDate": "2026-06-30T23:59:59+05:30",
"actions":[
{
"id": "temp_action_badge_1",
"actionName": "BADGE_EARN_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl",
"description": "Badge Issue",
"mandatoryPropertiesValues": {
"badgeMetaId": "<BADGE_META_ID>",
"badgeMetaName": "<BADGE_NAME>",
"referenceId": "<ORG_ID>_BulkEMFEvent_<UNIQUE_REF>",
"ownerType": "Loyalty_Promotion",
"delegateActionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.BadgeEarnActionImpl",
"Event Name": "BulkEMFEvent"
},
"mandatoryComplexPropertiesValues": {}
}
]
}
]
}
],
"promotionSchedule": {
"schedule": {
"startType": "PARTICULAR_DATE",
"scheduleDate": "2026-06-01T09:00:00+05:30",
"frequency": "DAILY"
}
}
}'OpenAPI definition
{
"openapi": "3.0.1",
"info": {
"title": "Sample API",
"version": "1.0.0",
"description": "API specification generated from cURL for POST /v3/promotions"
},
"servers":[
{
"url": "https://{host}"
}
],
"paths": {
"/v3/promotions": {
"post": {
"summary": "Operation for POST /v3/promotions",
"description": "Endpoint for POST /v3/promotions",
"operationId": "postV3promotions",
"parameters":[
{
"name": "cookie",
"in": "header",
"required": false,
"schema": {
"type": "string",
"example": "cqd4sJGKWK; intercom-device-id-m6855w1q=2cb436a9-655a-4e88-b754-8c3b11266d15; _ga=GA1.4.2043386039.1756703131; _gid=GA1.2.1414318397.1761018743; _gid=GA1.4.1414318397.1761018743; CS=2e610e15e7dede8cc6e16e9348477878; CTT=oHgB7DgLKOMvSaikcY0nrBuUpZaTM_ySBiefr08CLE_PMA40mLSK4MQW2-xvMD7S; CC=ufUVg-6Vvy3amNDwvuamTCghXIPtLq4wahTyUOz2f5AGiXNbQjjrfkw13Zw6FBe3; CCEXP=1761306963; CT=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6WyIyOTc0NjAiXSwib3JnSUQiOjAsImV4cCI6MTc2MTMwNjk2NCwiaWF0IjoxNzYxMjIwNTcwLCJpc3MiOiJjYXBpbGxhcnl0ZWNoLmNvbSIsImF1ZCI6ImNhcGlsbGFyeSxpbnRvdWNoLGFyeWEscmVvbixhcHBzIiwic291cmNlIjoiV0VCQVBQIiwicmVmZXJlbmNlSUQiOiI1MDc4Njk4MSJ9.rtfXZ_skDcP6m2itm8GLY6DmuAa27nVsDHIzUtmlc2k; userPreferenceSelected=50786981_RCID; OID=51174; intercom-session-m6855w1q=aUtiQVVabkhYTEtPTUlMQ2xKazBZWlE3WkoxOTl5QjZNaCtxRkZGT0ZVQnB2dzQwZUtUV25Jd0FDN3Z1QktxY0RaUnVwRzVkTXBteVVLT1FOSjkwY3REQUo3Mk5mN3hFZW0xeGtIVXZEN2M9LS1uMVVpQXdacWt3a1FsNllnWWRnVzdnPT0=--b5b8d75b79276dbb28d72a814f144a3e02185690; _ga_KL2T5V26LV=GS2.2.s1761286205$o20$g1$t1761286229$j36$l0$h0; fs_uid=#FSV9A#67c5eb74-78ba-4dff-80ee-decd6d52f587: fd6765ac-f998-42ec-b8dd-e462fe9bb0d0: 1761281569807: : 8#a77fbed8#/1788501324; AMP_dc8065a65e=JTdCJTIyZGV2aWNlSWQlMjIlM0ElMjIyMjNkMTFiNC05MGVkLTRmNTEtYWFiMi01YTgxZGIzYmIxYTQlMjIlMkMlMjJ1c2VySWQlMjIlM0ElMjJnZW9yZ2Uuam9obnNvbiU0MGNhcGlsbGFyeXRlY2guY29tJTIyJTJDJTIyc2Vzc2lvbklkJTIyJTNBMTc2MTI4OTk0NDc4MSUyQyUyMm9wdE91dCUyMiUzQWZhbHNlJTJDJTIybGFzdEV2ZW50VGltZSUyMiUzQTQ2MjUlMkMlMjJwYWdlQ291bnRlciUyMiUzQTAlN0Q=; _ga_Z68ZS274TW=GS2.2.s1761290249$o97$g1$t1761290256$j53$l0$h0; _ga_DMDM65MHS0=GS2.2.s1761290524$o30$g1$t1761290842$j57$l0$h0; _ga_KL2T5V26LV=GS2.4.s1761294802$o21$g0$t1761294813$j49$l0$h0"
}
},
{
"name": "x-cap-remote-user",
"in": "header",
"required": false,
"schema": {
"type": "string",
"example": "50786981"
}
}
],
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
},
"examples": {
"Created": {
"summary": "Created",
"value": {
"data": {
"metadata": {
"name": "ultimate_champion_challenge_deeply_nested",
"description": "Ultimate Champion Challenge with nested groups",
"programId": "2607",
"orgId": 100737,
"startDate": "2025-12-01T00:00:00Z",
"endDate": "2025-12-31T23:59:59Z",
"timezoneName": "Asia/Kolkata",
"promotionType": "GENERIC",
"status": "DRAFT",
"promoIdentifier": "ultimate-champion-2025-12",
"promotionId": 0,
"createdOn": "2025-10-15T12:45:59Z",
"lastModifiedOn": "2025-10-15T12:45:59Z",
"createdBy": 50786981,
"lastModifiedBy": 50786981,
"version": null,
"draftDetails": null,
"promotionMetadata":[],
"commonStrategies": null
},
"customerEnrolment": {
"enrolmentMethod": "TRANSACTION"
},
"activities":[
{
"type": "GROUP",
"id": "parent_group_ultimate_champion",
"name": "Ultimate Champion Main Goal",
"commonCycleActionMapping":[
{
"cycle": "Cycle_1",
"actions":[
{
"id": "action_ultimate_champion_reward",
"actionName": "ADVANCE_CURRENCY_ALLOCATION_ACTION",
"actionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl",
"description": "Ultimate Champion completion reward",
"mandatoryPropertiesValues": {
"PointsRoundingStrategy": "ACTUAL",
"SourceValueRoundingStrategy": "ACTUAL",
"DelayStrategy": "AS_DEFINED_IN_ALLOCATION_STRATEGY",
"Event Name": "TargetCompleted",
"ProRateOnSourceValue": "DEFINED_TARGET",
"PointType": "Main",
"ProrateFieldName": "",
"EvaluatedEntity": "USER",
"Currency": "POINTS"
},
"mandatoryComplexPropertiesValues": {},
"embeddedStrategies":[
{
"strategyTypeId": 1,
"propertyValues": {
"allocation_type": "FIXED",
"allocation_values": "5000"
},
"owner": "LOYALTY",
"updatedViaNewUI": true
},
{
"strategyTypeId": 3,
"propertyValues": {
"expiry_time_units": "NEVER",
"expiry_type": "SLAB_INDEPENDENT",
"expiry_time_values": "5000",
"expiry_from": "CURRENT_DATE"
},
"owner": "LOYALTY",
"updatedViaNewUI": true
}
]
}
],
"startDate": "2025-12-01",
"endDate": "2025-12-31"
}
],
"combinationType": "ALL",
"children":[
{
"type": "GROUP",
"id": "sub_group_elite_spending",
"name": "Part 1: Elite Spending Challenge",
"parentId": "parent_group_ultimate_champion",
"combinationType": "ANY",
"children":[
{
"type": "GROUP",
"id": "sub_sub_group_gadget_guru",
"name": "Path A: The Gadget Guru",
"parentId": "sub_group_elite_spending",
"combinationType": "ALL",
"children":[
{
"type": "SINGLE",
"id": "activity_spend_on_smartphones",
"name": "Spend 15k on Smartphones",
"parentId": "sub_sub_group_gadget_guru",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Spend 15k on Smartphones~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "SALES",
"targetEntity": "TRANSACTION",
"defaultValue": "15000",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
},
{
"type": "SINGLE",
"id": "activity_buy_accessories",
"name": "Buy 2 Mobile Accessories",
"parentId": "sub_sub_group_gadget_guru",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Buy 2 Mobile Accessories~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "TRANSACTION",
"defaultValue": "2",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
},
{
"type": "GROUP",
"id": "sub_sub_group_fashion_icon",
"name": "Path B: The Fashion Icon",
"parentId": "sub_group_elite_spending",
"combinationType": "ALL",
"children":[
{
"type": "SINGLE",
"id": "activity_spend_on_luxebrand",
"name": "Spend 10k on LuxeBrand",
"parentId": "sub_sub_group_fashion_icon",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Spend 10k on LuxeBrand~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "SALES",
"targetEntity": "TRANSACTION",
"defaultValue": "10000",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
},
{
"type": "SINGLE",
"id": "activity_buy_footwear",
"name": "Buy any Footwear",
"parentId": "sub_sub_group_fashion_icon",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Buy any Footwear~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "TRANSACTION",
"defaultValue": "1",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
},
{
"type": "GROUP",
"id": "sub_group_brand_engagement",
"name": "Part 2: Brand Engagement Challenge",
"parentId": "parent_group_ultimate_champion",
"combinationType": "ANY",
"children":[
{
"type": "GROUP",
"id": "sub_sub_group_frequent_shopper",
"name": "Path C: The Frequent Shopper",
"parentId": "sub_group_brand_engagement",
"combinationType": "ALL",
"children":[
{
"type": "SINGLE",
"id": "activity_make_5_transactions",
"name": "Make 5 transactions",
"parentId": "sub_sub_group_frequent_shopper",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Make 5 transactions~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "TRANSACTION",
"defaultValue": "5",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
},
{
"type": "SINGLE",
"id": "activity_buy_on_weekend",
"name": "Buy on a weekend",
"parentId": "sub_sub_group_frequent_shopper",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Buy on a weekend~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "TRANSACTION",
"defaultValue": "1",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
},
{
"type": "GROUP",
"id": "sub_sub_group_super_fan",
"name": "Path D: The Super Fan",
"parentId": "sub_group_brand_engagement",
"combinationType": "ALL",
"children":[
{
"type": "SINGLE",
"id": "activity_buy_3_categories",
"name": "Buy from 3 categories",
"parentId": "sub_sub_group_super_fan",
"event": "TransactionAdd",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Buy from 3 categories~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "TRANSACTION",
"defaultValue": "3",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
},
{
"type": "SINGLE",
"id": "activity_refer_friend",
"name": "Refer a friend",
"parentId": "sub_sub_group_super_fan",
"event": "FriendReferred",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
},
"milestones":[
{
"name": "ultimate_champion_challenge_deeply_nested~Refer a friend~Milestone 1",
"sameActionsForEveryCycle": false,
"differentTargetsForEveryCycle": false,
"trackingType": "DEFAULT",
"targetType": "COUNT",
"targetEntity": "USER",
"defaultValue": "1",
"preferredTillId": 50690981,
"targetEvaluationType": "FIXED_CALENDAR_WINDOW",
"leaderboardEnabled": false
}
],
"allCycles":[]
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
}
],
"ruleExpression": "true",
"expJSON": {
"arity": "literal",
"type": "boolean:primitive",
"value": "true"
}
}
],
"comments": null,
"parentId": null,
"version": 1,
"limits":[],
"liabilityOwnerSplitInfo":[],
"id": "68ef978767bab12998381c5d",
"workflowMetadata": {
"optin": {
"basedOn": null,
"audienceMapping": null,
"activities": null,
"restrictions": null
},
"enrolment": {
"basedOn": null,
"activities": null,
"audienceMapping": null,
"restrictions": null
}
}
},
"errors": null,
"warnings": null
}
}
}
}
},
"description": "Created"
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "Program Limit - Max 10k Points per Month V2"
},
"description": {
"type": "string",
"example": "Defines a program-wide monthly earning cap for Points currency."
},
"programId": {
"type": "integer",
"example": 2607
},
"startDate": {
"type": "string",
"format": "date-time",
"example": "2026-01-01T00:00:00Z"
},
"endDate": {
"type": "string",
"format": "date-time",
"example": "2026-12-31T23:59:59Z"
},
"promotionType": {
"type": "string",
"example": "GENERIC"
},
"status": {
"type": "string",
"example": "DRAFT"
},
"timezoneName": {
"type": "string",
"example": "Asia/Kolkata"
},
"promoIdentifier": {
"type": "string",
"example": "PROG_LIMIT_POINTS_MONTHLY_10K_V2"
},
"promotionCategory": {
"type": "string",
"nullable": true,
"example": "BROADCAST",
"description": "Identifies the promotion variant. Set to BROADCAST for broadcast promotions. Omit or leave null for standard activity-based promotions."
},
"promotionMetadata": {
"type": "array",
"example":[],
"items": {
"type": "string"
}
}
}
},
"customerEnrolment": {
"type": "object",
"properties": {
"enrolmentMethod": {
"type": "string",
"example": "TRANSACTION"
}
}
},
"activities": {
"type": "array",
"example":[
{
"id": "placeholder_activity_for_limit_promo",
"type": "SINGLE",
"name": "Placeholder Activity",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping": [
{
"cycle": "PlaceholderCycle",
"actions":[
{
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
}
]
}
]
}
],
"items": {
"type": "object",
"example": {
"id": "placeholder_activity_for_limit_promo",
"type": "SINGLE",
"name": "Placeholder Activity",
"event": "TransactionAdd",
"expJSON": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}",
"commonCycleActionMapping": [
{
"cycle": "PlaceholderCycle",
"actions":[
{
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
}
]
}
]
},
"properties": {
"id": {
"type": "string",
"example": "placeholder_activity_for_limit_promo"
},
"type": {
"type": "string",
"example": "SINGLE"
},
"name": {
"type": "string",
"example": "Placeholder Activity"
},
"event": {
"type": "string",
"example": "TransactionAdd"
},
"expJSON": {
"type": "string",
"example": "{\n \"arity\": \"literal\",\n \"type\": \"boolean:primitive\",\n \"value\": \"true\"\n}"
},
"commonCycleActionMapping": {
"type": "array",
"example":[
{
"cycle": "PlaceholderCycle",
"actions":[
{
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
}
]
}
],
"items": {
"type": "object",
"example": {
"cycle": "PlaceholderCycle",
"actions":[
{
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
}
]
},
"properties": {
"cycle": {
"type": "string",
"example": "PlaceholderCycle"
},
"actions": {
"type": "array",
"example":[
{
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
}
],
"items": {
"type": "object",
"example": {
"id": "placeholder_action",
"actionName": "NO_OP_ACTION",
"actionClass": "com.capillary.loyalty.engine.impl.action.NoOpAction",
"description": "Placeholder Action - Does Nothing",
"mandatoryPropertiesValues": {}
},
"properties": {
"id": {
"type": "string",
"example": "placeholder_action"
},
"actionName": {
"type": "string",
"example": "NO_OP_ACTION"
},
"actionClass": {
"type": "string",
"example": "com.capillary.loyalty.engine.impl.action.NoOpAction"
},
"description": {
"type": "string",
"example": "Placeholder Action - Does Nothing"
}
}
}
}
}
}
}
}
}
},
"limits": {
"type": "array",
"example":[
{
"entityScope": "PROGRAM",
"entityId": 2607,
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 10000,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "MONTHS",
"periodValue": 1
},
"active": true
}
],
"items": {
"type": "object",
"example": {
"entityScope": "PROGRAM",
"entityId": 2607,
"granularity": "USER",
"actionType": "AWARD_CURRENCY",
"actionSubTypeId": "Points",
"limitType": "SUM",
"limitValue": 10000,
"period": {
"periodType": "FIXED_CALENDAR_WINDOW",
"periodUnit": "MONTHS",
"periodValue": 1
},
"active": true
},
"properties": {
"entityScope": {
"type": "string",
"example": "PROGRAM"
},
"entityId": {
"type": "integer",
"example": 2607
},
"granularity": {
"type": "string",
"example": "USER"
},
"actionType": {
"type": "string",
"example": "AWARD_CURRENCY"
},
"actionSubTypeId": {
"type": "string",
"example": "Points"
},
"limitType": {
"type": "string",
"example": "SUM"
},
"limitValue": {
"type": "integer",
"example": 10000
},
"period": {
"type": "object",
"properties": {
"periodType": {
"type": "string",
"example": "FIXED_CALENDAR_WINDOW"
},
"periodUnit": {
"type": "string",
"example": "MONTHS"
},
"periodValue": {
"type": "integer",
"example": 1
}
}
},
"active": {
"type": "boolean",
"example": true
}
}
}
},
"liabilityOwnerSplitInfo": {
"type": "array",
"example":[],
"items": {
"type": "string"
}
},
"broadcastMetadata": {
"type": "object",
"description": "Defines audience targeting for broadcast promotions. Required when promotionCategory is BROADCAST.",
"properties": {
"source": {
"type": "string",
"example": "AUDIENCE_FILTER",
"description": "Specifies the audience source type. Supported value: AUDIENCE_FILTER."
},
"audienceFilter": {
"type": "object",
"properties": {
"audienceListIds": {
"type": "array",
"items": {
"type": "integer"
},
"example":[612232354, 612232355],
"description": "List of audience group IDs to receive the reward."
}
}
}
}
},
"promotionSchedule": {
"type": "object",
"description": "Defines the delivery schedule for broadcast promotions. Required when promotionCategory is BROADCAST.",
"properties": {
"schedule": {
"type": "object",
"properties": {
"startType": {
"type": "string",
"example": "IMMEDIATE",
"description": "Defines when the broadcast starts. Supported values: IMMEDIATE, PARTICULAR_DATE."
},
"scheduleDate": {
"type": "string",
"nullable": true,
"example": "2026-06-01T09:00:00+05:30",
"description": "Scheduled start date and time in ISO 8601 format. Required when startType is PARTICULAR_DATE."
},
"frequency": {
"type": "string",
"example": "ONCE",
"description": "Specifies how often rewards are issued. Supported values: ONCE, DAILY."
}
}
}
}
}
},
"description": "Request body as an object"
},
"examples": {}
}
},
"description": "Request body",
"required": false
},
"x-readme": {
"code-samples":[
{
"code": "curl --location 'https://eu.api.capillarytech.com/v3/promotions' \\\n--header 'content-type: application/json' \\\n--header 'Authorization: Basic <token>' \\\n--data '{\n \"metadata\": {\n \"name\": \"Single Activity Promotion\",\n \"description\": \"A promotion with single activity\",\n \"programId\": 973,\n \"startDate\": \"2026-02-02T05:11:00Z\",\n \"endDate\": \"2026-02-28T05:11:59Z\",\n \"promotionType\": \"GENERIC\",\n \"status\": \"DRAFT\",\n \"promoIdentifier\": \"single-activity-promotion\",\n \"timezoneName\": \"Asia/Kolkata\",\n \"promotionMetadata\": [],\n \"createdBy\": 75139931,\n \"lastModifiedBy\": 75139931,\n },\n \"customerEnrolment\": {\n \"enrolmentMethod\": \"TRANSACTION\"\n },\n \"liabilityOwnerSplitInfo\":[\n {\n \"liabilityOwnerId\": 82,\n \"componentType\": \"PROMOTION\",\n \"ratio\": 100,\n \"active\": true,\n \"liabilityOwnerName\": \"DocDemoDefaultProgram\",\n \"liabilityOwnerType\": \"PROGRAM\",\n \"orgId\": 100737\n }\n ],\n \"activities\":[\n {\n \"id\": \"activity_1770009105303\",\n \"name\": \"Activity 1\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"milestones\": [],\n \"commonCycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T05:11:00Z\",\n \"endDate\": \"2026-02-28T05:11:59Z\",\n \"actions\":[\n {\n \"id\": \"temp_06a1a899-99e8-4f5e-8910-a3b2b51aa142\",\n \"actionName\": \"ADVANCE_CURRENCY_ALLOCATION_ACTION\",\n \"actionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl\",\n \"mandatoryPropertiesValues\": {\n \"PointType\": \"Main\",\n \"PointsRoundingStrategy\": \"ACTUAL\",\n \"ProRateOnSourceValue\": \"EVENT_DEFAULT_VALUE\",\n \"EvaluatedEntity\": \"USER\",\n \"Currency\": \"POINTS\",\n \"Event Name\": \"TransactionAdd\",\n \"DelayStrategy\": \"AS_DEFINED_IN_ALLOCATION_STRATEGY\",\n \"ProrateFieldName\": \"\",\n \"SourceValueRoundingStrategy\": \"ACTUAL\",\n \"delegateActionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl\"\n },\n \"mandatoryComplexPropertiesValues\": {},\n \"description\": \"Advanced currency allocation action\",\n \"embeddedStrategies\":[\n {\n \"strategyTypeId\": 1,\n \"propertyValues\": \"{\\\"allocation_type\\\":\\\"FIXED\\\",\\\"allocation_values\\\":\\\"100,100,100,100,100,100,100,100\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true,\n \"strategySubType\": \"DEFAULT\"\n },\n {\n \"strategyTypeId\": 3,\n \"propertyValues\": \"{\\\"expiry_type\\\":\\\"SLAB_INDEPENDENT\\\",\\\"expiry_from\\\":\\\"CURRENT_DATE\\\",\\\"expiry_time_units\\\":\\\"FIXED_DATE,FIXED_DATE,FIXED_DATE,FIXED_DATE,FIXED_DATE,FIXED_DATE,FIXED_DATE,FIXED_DATE\\\",\\\"expiry_time_values\\\":\\\"2026-02-28,2026-02-28,2026-02-28,2026-02-28,2026-02-28,2026-02-28,2026-02-28,2026-02-28\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true,\n \"strategySubType\": \"DEFAULT\"\n }\n ]\n }\n ]\n }\n ],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"binary_operation\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\">\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"object_dereference\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"tx:object:primitive\\\",\\n \\\"value\\\": \\\"currentTxn\\\"\\n },\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"value\\\": \\\"value\\\"\\n }\\n ]\\n },\\n {\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"number:primitive\\\",\\n \\\"value\\\": \\\"1000\\\"\\n }\\n ]\\n}\"\n }\n ],\n \"limits\":[\n {\n \"granularity\": \"USER\",\n \"actionType\": \"AWARD_CURRENCY\",\n \"limitType\": \"COUNT\",\n \"limitValue\": 100,\n \"period\": {\n \"periodType\": \"NON_PERIOD_BASED\"\n },\n \"actionSubTypeId\": \"Points\"\n }\n ],\n \"workflowMetadata\": {\n \"optin\": {},\n \"enrolment\": {}\n }\n}'",
"language": "shell",
"name": "Single activity"
},
{
"code": "curl -L -g 'https://{{eu}}/v3/promotions' \\\n-H 'Content-Type: application/json' \\\n-H 'X-CAP-API-AUTH-ORG-ID: 100737' \\\n-H 'Authorization: Basic bWU6cGFzc3dvcmQ=' \\\n'{\n \"metadata\": {\n \"name\": \"Single Milestone Promotion\",\n \"description\": \"Single Milestone Promotion\",\n \"programId\": 973,\n \"startDate\": \"2026-02-02T12:28:00+05:30\",\n \"endDate\": \"2026-02-28T12:28:59+05:30\",\n \"promotionType\": \"GENERIC\",\n \"status\": \"DRAFT\",\n \"promoIdentifier\": \"single-milestone-promotion\",\n \"timezoneName\": \"Asia/Kolkata\",\n \"promotionMetadata\":[],\n \"createdBy\": 75139931,\n \"lastModifiedBy\": 75139931,\n },\n \"customerEnrolment\": {\n \"enrolmentMethod\": \"TRANSACTION\"\n },\n \"liabilityOwnerSplitInfo\": [],\n \"activities\":[\n {\n \"id\": \"activity_1770015539223\",\n \"name\": \"Activity 1\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"milestones\":[\n {\n \"name\": \"Single Milestone Promotion~Activity 1~Milestone 1770015543\",\n \"trackingType\": \"DEFAULT\",\n \"targetEvaluationType\": \"FIXED_CALENDAR_WINDOW\",\n \"frequencyType\": \"WEEKLY\",\n \"sameActionsForEveryCycle\": true,\n \"differentTargetsForEveryCycle\": false,\n \"leaderboardEnabled\": false,\n \"preferredTillId\": 75216507,\n \"targetEntity\": \"TRANSACTION\",\n \"targetType\": \"COUNT\",\n \"cycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T12:28:00+05:30\",\n \"endDate\": \"2026-02-08T23:59:59+05:30\",\n \"defaultValue\": \"3\",\n \"actions\": []\n },\n {\n \"cycle\": \"Cycle_2\",\n \"startDate\": \"2026-02-09T00:00:00+05:30\",\n \"endDate\": \"2026-02-15T23:59:59+05:30\",\n \"defaultValue\": \"3\",\n \"actions\":[]\n },\n {\n \"cycle\": \"Cycle_3\",\n \"startDate\": \"2026-02-16T00:00:00+05:30\",\n \"endDate\": \"2026-02-22T23:59:59+05:30\",\n \"defaultValue\": \"3\",\n \"actions\":[]\n },\n {\n \"cycle\": \"Cycle_4\",\n \"startDate\": \"2026-02-23T00:00:00+05:30\",\n \"endDate\": \"2026-02-28T12:28:59+05:30\",\n \"defaultValue\": \"3\",\n \"actions\":[]\n }\n ]\n }\n ],\n \"commonCycleActionMapping\":[],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"binary_operation\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\">\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"object_dereference\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"tx:object:primitive\\\",\\n \\\"value\\\": \\\"currentTxn\\\"\\n },\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"value\\\": \\\"value\\\"\\n }\\n ]\\n },\\n {\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"number:primitive\\\",\\n \\\"value\\\": \\\"1000\\\"\\n }\\n ]\\n}\"\n }\n ],\n \"workflowMetadata\": {\n \"optin\": {},\n \"enrolment\": {}\n }\n}'",
"language": "shell",
"name": "Single Milestone"
},
{
"code": "curl -L -g '{\n \"metadata\": {\n \"name\": \"Two Activities Promotion\",\n \"description\": \"Two Activities Promotion\",\n \"programId\": 973,\n \"startDate\": \"2026-02-02T12:31:00+05:30\",\n \"endDate\": \"2026-02-28T12:31:59+05:30\",\n \"promotionType\": \"GENERIC\",\n \"status\": \"DRAFT\",\n \"promoIdentifier\": \"two-activities-promotion\",\n \"timezoneName\": \"Asia/Kolkata\",\n \"promotionMetadata\":[],\n \"createdBy\": 75139931,\n \"lastModifiedBy\": 75139931,\n },\n \"customerEnrolment\": {\n \"enrolmentMethod\": \"TRANSACTION\"\n },\n \"liabilityOwnerSplitInfo\": [],\n \"activities\":[\n {\n \"id\": \"activity_1770015688839\",\n \"name\": \"Activity 1\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"milestones\": [],\n \"commonCycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T12:31:00+05:30\",\n \"endDate\": \"2026-02-28T12:31:59+05:30\",\n \"actions\":[\n {\n \"id\": \"temp_c86386d4-53c8-461e-897b-89a24298786e\",\n \"actionName\": \"ADVANCE_CURRENCY_ALLOCATION_ACTION\",\n \"actionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl\",\n \"mandatoryPropertiesValues\": {\n \"PointsRoundingStrategy\": \"ACTUAL\",\n \"SourceValueRoundingStrategy\": \"ACTUAL\",\n \"DelayStrategy\": \"AS_DEFINED_IN_ALLOCATION_STRATEGY\",\n \"Event Name\": \"TransactionAdd\",\n \"ProRateOnSourceValue\": \"EVENT_DEFAULT_VALUE\",\n \"PointType\": \"Main\",\n \"ProrateFieldName\": \"\",\n \"EvaluatedEntity\": \"USER\",\n \"Currency\": \"POINTS\",\n \"delegateActionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl\"\n },\n \"mandatoryComplexPropertiesValues\": {},\n \"description\": \"Advanced currency allocation action\",\n \"embeddedStrategies\":[\n {\n \"strategyTypeId\": 1,\n \"propertyValues\": \"{\\\"allocation_type\\\":\\\"FIXED\\\",\\\"allocation_values\\\":\\\"100,100,100,100,100,100,100,100\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n },\n {\n \"strategyTypeId\": 3,\n \"propertyValues\": \"{\\\"expiry_time_units\\\":\\\"NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER\\\",\\\"expiry_type\\\":\\\"SLAB_INDEPENDENT\\\",\\\"expiry_time_values\\\":\\\"100,100,100,100,100,100,100,100\\\",\\\"expiry_from\\\":\\\"CURRENT_DATE\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n }\n ]\n }\n ]\n }\n ],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"binary_operation\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\">\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"object_dereference\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"tx:object:primitive\\\",\\n \\\"value\\\": \\\"currentTxn\\\"\\n },\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"value\\\": \\\"value\\\"\\n }\\n ]\\n },\\n {\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"number:primitive\\\",\\n \\\"value\\\": \\\"1000\\\"\\n }\\n ]\\n}\"\n },\n {\n \"id\": \"activity_1770015716472\",\n \"name\": \"Activity 2\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"milestones\": [],\n \"commonCycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T12:31:00+05:30\",\n \"endDate\": \"2026-02-28T12:31:59+05:30\",\n \"actions\":[\n {\n \"id\": \"temp_1cc155bf-0bcb-4488-b290-7851982c82d6\",\n \"actionName\": \"ADVANCE_CURRENCY_ALLOCATION_ACTION\",\n \"actionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl\",\n \"mandatoryPropertiesValues\": {\n \"PointsRoundingStrategy\": \"ACTUAL\",\n \"SourceValueRoundingStrategy\": \"ACTUAL\",\n \"DelayStrategy\": \"AS_DEFINED_IN_ALLOCATION_STRATEGY\",\n \"Event Name\": \"TransactionAdd\",\n \"ProRateOnSourceValue\": \"EVENT_DEFAULT_VALUE\",\n \"PointType\": \"Main\",\n \"ProrateFieldName\": \"\",\n \"EvaluatedEntity\": \"USER\",\n \"Currency\": \"POINTS\",\n \"delegateActionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl\"\n },\n \"mandatoryComplexPropertiesValues\": {},\n \"description\": \"Advanced currency allocation action\",\n \"embeddedStrategies\":[\n {\n \"strategyTypeId\": 1,\n \"propertyValues\": \"{\\\"allocation_type\\\":\\\"FIXED\\\",\\\"allocation_values\\\":\\\"500,500,500,500,500,500,500,500\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n },\n {\n \"strategyTypeId\": 3,\n \"propertyValues\": \"{\\\"expiry_time_units\\\":\\\"NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER\\\",\\\"expiry_type\\\":\\\"SLAB_INDEPENDENT\\\",\\\"expiry_time_values\\\":\\\"100,100,100,100,100,100,100,100\\\",\\\"expiry_from\\\":\\\"CURRENT_DATE\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n }\n ]\n }\n ]\n }\n ],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"binary_operation\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\">\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"object_dereference\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"tx:object:primitive\\\",\\n \\\"value\\\": \\\"currentTxn\\\"\\n },\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"real:object:primitive\\\",\\n \\\"value\\\": \\\"value\\\"\\n }\\n ]\\n },\\n {\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"number:primitive\\\",\\n \\\"value\\\": \\\"5000\\\"\\n }\\n ]\\n}\"\n },\n {\n \"id\": \"activity_1770015742170\",\n \"name\": \"Activity 3\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"milestones\":[],\n \"commonCycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T12:31:00+05:30\",\n \"endDate\": \"2026-02-28T12:31:59+05:30\",\n \"actions\": []\n }\n ],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\"true\\\"\\n}\"\n }\n ],\n \"workflowMetadata\": {\n \"optin\": {},\n \"enrolment\": {}\n }\n}'",
"language": "shell",
"name": "Two activities"
},
{
"code": "curl -L 'https://eu.api.capillarytech.com/v3/promotions' \\\n-H 'Content-Type: application/json' \\\n-H 'X-CAP-API-AUTH-ORG-ID: 51174' \\\n-H 'key: Cookie' \\\n-d '{\n \"metadata\": {\n \"name\": \"Group Promotion\",\n \"description\": \"Group Promotion\",\n \"programId\": 973,\n \"startDate\": \"2026-02-02T12:34:00+05:30\",\n \"endDate\": \"2026-02-28T12:34:59+05:30\",\n \"promotionType\": \"GENERIC\",\n \"status\": \"DRAFT\",\n \"promoIdentifier\": \"group-promotion\",\n \"timezoneName\": \"Asia/Kolkata\",\n \"promotionMetadata\":[],\n \"createdBy\": 75139931,\n \"lastModifiedBy\": 75139931,\n },\n \"customerEnrolment\": {\n \"enrolmentMethod\": \"TRANSACTION\"\n },\n \"liabilityOwnerSplitInfo\": [],\n \"activities\":[\n {\n \"id\": \"group_1770015857736\",\n \"type\": \"GROUP\",\n \"name\": \"Group 1\",\n \"combinationType\": \"ALL\",\n \"commonCycleActionMapping\":[\n {\n \"cycle\": \"Cycle_1\",\n \"startDate\": \"2026-02-02T12:34:00+05:30\",\n \"endDate\": \"2026-02-28T12:34:59+05:30\",\n \"actions\":[\n {\n \"id\": \"action_1770015984787\",\n \"actionName\": \"ADVANCE_CURRENCY_ALLOCATION_ACTION\",\n \"actionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl\",\n \"mandatoryPropertiesValues\": {\n \"PointsRoundingStrategy\": \"ACTUAL\",\n \"SourceValueRoundingStrategy\": \"ACTUAL\",\n \"DelayStrategy\": \"AS_DEFINED_IN_ALLOCATION_STRATEGY\",\n \"Event Name\": \"TargetCompleted\",\n \"ProRateOnSourceValue\": \"EVENT_DEFAULT_VALUE\",\n \"PointType\": \"Main\",\n \"ProrateFieldName\": \"\",\n \"EvaluatedEntity\": \"USER\",\n \"Currency\": \"POINTS\",\n \"delegateActionClass\": \"com.capillary.shopbook.pointsengine.endpoint.impl.action.AdvanceCurrencyAllocationActionImpl\"\n },\n \"mandatoryComplexPropertiesValues\": {},\n \"description\": \"Advanced currency allocation action\",\n \"embeddedStrategies\":[\n {\n \"strategyTypeId\": 1,\n \"propertyValues\": \"{\\\"allocation_type\\\":\\\"FIXED\\\",\\\"allocation_values\\\":\\\"100,100,100,100,100,100,100,100\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n },\n {\n \"strategyTypeId\": 3,\n \"propertyValues\": \"{\\\"expiry_time_units\\\":\\\"NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER,NEVER\\\",\\\"expiry_type\\\":\\\"SLAB_INDEPENDENT\\\",\\\"expiry_time_values\\\":\\\"100,100,100,100,100,100,100,100\\\",\\\"expiry_from\\\":\\\"CURRENT_DATE\\\"}\",\n \"owner\": \"LOYALTY\",\n \"updatedViaNewUI\": true\n }\n ]\n }\n ]\n }\n ],\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\"true\\\"\\n}\",\n \"children\":[\n {\n \"id\": \"sub_activity_1770015859452\",\n \"name\": \"Sub-Activity 1\",\n \"type\": \"SINGLE\",\n \"event\": \"TransactionAdd\",\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\"true\\\"\\n}\",\n \"milestones\":[\n {\n \"name\": \"Group Promotion~Sub-Activity 1~Milestone 1770015859\",\n \"trackingType\": \"DEFAULT\",\n \"leaderboardEnabled\": false,\n \"preferredTillId\": 75216507,\n \"targetEntity\": \"TRANSACTION\",\n \"targetType\": \"GROSS_SALES\",\n \"defaultValue\": \"1000\"\n }\n ]\n },\n {\n \"id\": \"sub_activity_1770015878202\",\n \"name\": \"Sub-Activity 2\",\n \"type\": \"SINGLE\",\n \"event\": \"VoucherRedemption\",\n \"expJSON\": \"{\\n \\\"arity\\\": \\\"binary_operation\\\",\\n \\\"type\\\": \\\"boolean:primitive\\\",\\n \\\"value\\\": \\\"==\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"object_dereference\\\",\\n \\\"type\\\": \\\"integer:number:primitive\\\",\\n \\\"operands\\\":[\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"couponRedemptionEvent:object:primitive\\\",\\n \\\"value\\\": \\\"currentEvent\\\"\\n },\\n {\\n \\\"arity\\\": \\\"name\\\",\\n \\\"type\\\": \\\"integer:number:primitive\\\",\\n \\\"value\\\": \\\"redeemedCouponSeriesId\\\"\\n }\\n ]\\n },\\n {\\n \\\"arity\\\": \\\"literal\\\",\\n \\\"type\\\": \\\"number:primitive\\\",\\n \\\"value\\\": \\\"100\\\"\\n }\\n ]\\n}\",\n \"milestones\":[\n {\n \"name\": \"Group Promotion~Sub-Activity 2~Milestone 1770015878\",\n \"trackingType\": \"DEFAULT\",\n \"leaderboardEnabled\": false,\n \"preferredTillId\": 75216507,\n \"targetEntity\": \"EVENT\",\n \"targetType\": \"COUNT\",\n \"defaultValue\": \"1\"\n }\n ]\n }\n ]\n }\n ],\n \"workflowMetadata\": {\n \"optin\": {},\n \"enrolment\": {}\n }\n}'",
"language": "shell",
"name": "Group of activities"
}
],
"samples-languages":[
"shell"
]
}
}
}
},
"x-readme": {}
}