This endpoint updates an existing unified promotion using its unique ID. You must provide the complete promotion object in the request body, including all fields you wish to keep, as this operation typically replaces the existing promotion data with the data provided.
Example request
curl --location --request PUT 'https://{Host}/api_gateway/v1/promotions/{promotion_id}' \
--header 'Content-Type: application/json' \
--header 'X-CAP-API-AUTH-ORG-ID: 100232' \
--header 'user-agent: pyapps_auto_Promotion_Engine_Eucrm_Smoke' \
--header 'Authorization: Basic bmFtYMWJmYjM5OGM5ZmM2YjZlY2I2MmEy' \
--data '{
    "name": "CODE_Promotion_Test_17573886",
    "orgId": 100027,
    "priority": 0,
    "active": true,
    "messageLabel": "test!!",
    "type": "CODE",
    "condition": {
      "type": "CART",
      "cartCondition": {
        "kpi": "SUBTOTAL",
        "operator": "EQUALS",
        "value": 250.0
      }
    },
    "action": {
      "type": "CART_BASED",
      "cartBasedAction": {
        "type": "ABSOLUTE",
        "value": 25.0
      }
    },
    "createdBy": 70707,
    "createdOn": 0,
    "lastUpdatedBy": 70707,
    "startDate": "1857388651000",
    "endDate": "1857475051000",
    "campaignId": 39077,
    "mode": "DISCOUNT",
    "promotionRestrictions": {
      "Code": [
        {
          "kpi": "REDEMPTION",
          "limit": 1
        }
      ]
    },
    "isStackable": false
  }'Prerequisites
- Authentication: Basic or OAuth authentication.
- Default access group
Rate limit
- Demo and Testing Clusters: 1,000 requests per minute per API key
- Other Organizations: The rate limit is brand-specific.
To modify the limit, create a ticket with the Capillary Product support team.
Body Parameters
| Type | Field | Required | Description | 
|---|---|---|---|
| Object | metadata | Yes | Contains all core promotion settings. See The metadata Object table below. | 
| Object | customerEnrolment | Yes | Defines who is initially eligible. See Customer Enrollment & Workflows table below. | 
| Array of Object | activities | Yes | Defines the triggers and rewards. See The activities Object table below. | 
| Object | workflowMetadata | Optional | Defines dynamic opt-in or enrollment rules. See Customer Enrollment & Workflows table below. | 
| Array of Object | limits | Optional | Sets usage limits. See The limits Object table below. | 
| Array of Object | liabilityOwnerSplitInfo | Optional | Defines cost splitting. See The liabilityOwnerSplitInfo Object table below. | 
| string | comments | Optional | Internal comments for the promotion. Example: "Initial draft for review" | 
| string | parentId | Optional | Parent promotion ID, if cloning. Example: "68f708709c1b226be345abcd" | 
Metadata object table
Specifies the essential configuration details for the promotion. This object holds the core identifiers and timing of a promotion.
| Field | Type | Required | Description | 
|---|---|---|---|
| name | string | Yes | Specifies the unique name of the promotion, used for identification.  Supported Values: String (max length 200). | 
| orgId | integer | Yes | Indicates the unique organization identifier the promotion belongs to. This ensures the promotion runs under the correct business account. Supported Values: Valid Organization ID (integer). | 
| startDate | string | Yes | Specifies the active start date and time when the promotion becomes effective. This marks the exact moment customers can start qualifying for the "Weekend Double Points". | 
| endDate | string | Yes | Specifies the active end date and time when the promotion stops being effective. This is the cut-off time for earning double points in the weekend offer. | 
| promotionType | string | Yes | Indicates the nature of the reward or promotion type, used for categorization. | 
| status | enum | Yes | Specifies the initial status upon creation, determining its visibility and execution state. Supported Values: 
 | 
| description | string | Optional | Indicates a brief description of the promotion's purpose for internal reference. E.g., "Standard weekend points multiplier campaign". | 
| programId | string | Optional | Specifies the loyalty program unique identifier to which the promotion is associated with, linking it to that program's points system. Program ID. Example: "2607" or "MAIN_REWARDS" | 
| timezoneName | string | Optional | Defines the timezone for interpreting the start and end dates, ensuring the "Weekend Double Points" offer starts and ends correctly in the target region. Supported Values: Valid IANA Time Zone Database name. Example: "Asia/Kolkata" or "America/New_York" | 
| promoIdentifer | string | Optional | Specifies a unique string identifier for the promotion. | 
| loyaltyEarningType | enum | Optional | Defines how rewards are issued.  | 
| loyaltyConfigMetaData | Object | Optional | Defines complex rules for promotion interaction. You can use this to prevent the "Weekend Double Points" from applying if an employee discount is used. Supported Values: A valid LoyaltyConfigMetaDto object. Example: { "isStackable": false, "isExclusive": true } Refer "loyaltyConfigMetaData" table below for the full structure | 
| promotionMetadata | Array (Object) | Optional | Defines a list of custom key-value pairs for additional metadata, often for reporting or integration purposes. You can tag the "Weekend Double Points" offer with {"key": "CampaignTheme", "value": "Seasonal"}. Supported Values: Array of PromotionMetadata objects. Example: [ { "key": "CampaignCode", "value": "FALL25" } ] Refer "promotionMetadata" table below for the full structure | 
Nested: loyaltyConfigMetaData Object
| Field | Type | Required | Description | 
|---|---|---|---|
| isStackable | boolean | Optional | Indicates if this promotion can be combined with others. false means the "Weekend Double Points" cannot be combined with a "10% Off" coupon in the same transaction. | 
| isExclusive | boolean | Optional | Indicates if this promotion cancels out all other non-stackable promotions when applied. If true, applying this bonus prevents any other offer, even stackable ones. Supported Values: true, false. | 
| isAlwaysApply | boolean | Optional | Indicates if the promotion should always be applied automatically when conditions are met. true ensures "Weekend Double Points" apply without needing a code or manual selection. Supported Values: true, false. Example: true | 
| isConsideredForRanking | boolean | Optional | Indicates if earnings from this promotion should contribute to customer tier ranking calculations. true means the extra points from "Weekend Double Points" help customers reach the next loyalty tier faster. Supported Values: true, false. Example: true | 
| skipEarnedDateCheckOnRedeem | boolean | Optional | Specifies to skip validation of the reward's earned date during redemption, allowing redemption before official earning time. false ensures points from "Weekend Double Points" can only be used after they're properly awarded. | 
Nested: promotionMetadata Object
| Field | Type | Required | Description | 
|---|---|---|---|
| isBrandDefined | string | Optional | Indicates if the metadata key is custom (true) or system-defined (false). For a custom "CampaignTheme" tag, this value is true. | 
| key | string | Optional | Specifies the metadata key name.This key is used for tracking internal campaigns. | 
| value | string | Optional | Specifies the metadata key value.This value is used for the specific code for the campaign. Supported Values: String. Example: "FALL25" | 
Requirement 1: Comprehensive Loyalty Config & Metadata TagsStyleSavvy Boutique has configured a promotion named "StyleSavvy VIP Early Access-lock," active from November 10th to November 15th, 2025. The condition is: if any customer makes a transaction during this period, the system will automatically apply this promotion. As a result, points awarded will count towards the customer's tier ranking, and any associated rewards can be redeemed immediately. The promotion itself cannot be stacked or combined with other offers, and the primary action triggered is the awarding of points based on predefined strategies.
curl --location 'https://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "StyleSavvy VIP Early Access-lock",
        "description": "Always-apply, counts for rank, immediate redeem. VIP Early Bird tags.",
        "orgId": 100737,
        "programId": 2607,
        "startDate": "2025-11-10T00:00:00+05:30",
        "endDate": "2025-11-15T23:59:59+05:30",
        "promotionType": "GENERIC",
        "status": "DRAFT",
        "timezoneName": "Asia/Kolkata",
        "promoIdentifer": "SS_VIP_EARLY_NOV25_UI",
        "loyaltyEarningType": null,
        "loyaltyConfigMetaData": {
            "isStackable": false,
            "isExclusive": false,
            "isAlwaysApply": true,
            "isConsideredForRanking": true,
            "skipEarnedDateCheckOnRedeem": true
        },
        "promotionMetadata": [
            {
                "isBrandDefined": "true",
                "key": "Access",
                "value": "VIP"
            },
            {
                "isBrandDefined": "true",
                "key": "Event",
                "value": "EarlyBird"
            }
        ]
    },
    "customerEnrolment": {
        "enrolmentMethod": "TRANSACTION",
        "audienceGroups": []
    },
    "activities": [
        {
            "id": "activity_1761xxxxxx01", "type": "SINGLE", "name": "VIP Activity", "event": "TransactionAdd",
            "expJSON": "{\n  \"arity\": \"literal\",\n  \"type\": \"boolean:primitive\",\n  \"value\": \"true\"\n}",
            "commonCycleActionMapping": [{
                "cycle": "Cycle_1", "startDate": "2025-11-10", "endDate": "2025-11-15",
                "actions": [{
                    "id":"temp_action_vip", "actionName": "AWARD_POINTS_ACTION",
                    "actionClass":"com.capillary.shopbook.pointsengine.endpoint.impl.action.AwardPointsActionImpl",
                    "description":"Award VIP Points",
                    "mandatoryPropertiesValues": {"AwardStrategy":"109010","ExpiryStrategy":"109006"},
                    "mandatoryComplexPropertiesValues": {}, "embeddedStrategies": []
                }]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Requirement 2: Generic Promo + ISSUE_AND_EARNBrand Requirement: 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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Adventure Quest Gear Up Challenge-UI",
        "description": "Generic promo for Gear Up Challenge. Issue and Earn.",
        "orgId": 100737,
        "programId": 2607,
        "startDate": "2025-12-01T00:00:00+05:30",
        "endDate": "2025-12-31T23:59:59+05:30",
        "promotionType": "GENERIC",
        "status": "DRAFT",
        "timezoneName": "Asia/Kolkata",
        "promoIdentifer": "AQ_GEARUP_DEC25_UI",
        "loyaltyEarningType": "ISSUE_AND_EARN",
        "loyaltyConfigMetaData": {
            "isStackable": false, "isExclusive": false, "isAlwaysApply": false, "isConsideredForRanking": false, "skipEarnedDateCheckOnRedeem": null
        },
        "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-01", "endDate": "2025-12-31",
                "actions": [{
                    "id":"temp_action_badge", "actionName": "AWARD_BADGE", "actionClass":"...",
                    "description":"Award Gear Up Badge",
                    "mandatoryPropertiesValues": {"badgeId": "GEAR_UP_DEC25"},
                    "mandatoryComplexPropertiesValues": {}, "embeddedStrategies": []
                }]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Customer enrollment and workflows object table
These objects define who is eligible for the promotion and how they get in, both at the start (customerEnrolment) and dynamically during the promotion (workflowMetadata).
customerEnrolment object table
Defines the initial set of customers eligible for the promotion.
| Field | Type | Required | Description | 
|---|---|---|---|
| enrolmentMethod | enum | Optional | Defines the primary enrollment type.  Example: A cafe's "Holiday Bonus" promo. Any customer who makes any purchase during December is automatically enrolled and starts earning. 
 Example: A brand wants to reward 50 specific contest winners. A manager uploads a CSV file containing only those 50 customer IDs. Only those 50 people are enrolled. 
 Example: A "VIP Exclusive Sale." Before the sale starts, the system checks its database and pre-enrolls everyone who is already in the "Gold Tier" customer segment. If you are not in the "Gold Tier" group before it starts, you are not included. | 
| audienceGroups | Array (Object) | Conditional | List of audience segments to pre-enroll. | 
| ..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" | 
workflowMetadata Object
Defines dynamic (post-start) enrollment or opt-in rules.
| Field | Type | Required | Description | 
|---|---|---|---|
| enrolment | Object | Optional | Specifies rules for automatic dynamic enrollment. See Nested: enrolment and optin Object table below. | 
| optin | Object | Optional | Specifies rules for customer-managed opt-in. See Nested: enrolment and optin Object table below. | 
Nested: enrolment and optin Object
The structure for enrolment and optin objects is identical.
| Field | Type | Required | Description | 
|---|---|---|---|
| basedOn | enum | Optional | Trigger type. | 
| activities | Array (Object) | Conditional | A list of Activity Objects  that trigger the enrollment or opt-in. | 
| audienceMapping | Array (Object) | Conditional | List of audience groups that trigger the enrollment or opt-in. | 
| ..groupId | integer | Optional | The ID of the audience group. Example: 12345 | 
| ..groupName | string | Optional | Informational name of the audience group. Example: "Gold Tier" | 
| restrictions | Object | Optional | Applies limits specifically to this workflow. See Nested: Promotion Restrictions Object table below. | 
Nested: promotion restrictions object
Defines limits for the enrolment or optin workflow.
| Field | Type | Required | Description | 
|---|---|---|---|
| optinExpiryBasedOn | Object | Optional | Defines expiry for the user's opt-in status. | 
| ..type | enum | Optional | Expiry method. Supported Values: Example: A "Weekend Sale" runs from Friday to Sunday. You opt-in on Friday. Your opt-in status is active until the promotion itself ends on Sunday night. 
 Example: A "7-Day Free Trial." You opt-in by signing up on a Tuesday. Your trial (your opt-in status) lasts for exactly 7 days, expiring next Tuesday. If your friend signs up on Friday, their trial expires next Friday. 
 Example: A "Summer Contest" where you can opt-in anytime. The rules state all entries and opt-in statuses expire on December 31st. If you opt-in on July 1st or December 30th, your status still ends on December 31st. | 
| ..value | integer | Optional | Duration until when the opt-in lasts. Example: 30 , which defines the opt-in expiry as 30 days.
Required if type is  | 
| ..expiryDate | string | Optional | The exact date and time opt-in expires. Example: "2026-12-31T23:59:59Z" | 
| enrolmentExpiryBasedOn | Object | Optional | Defines expiry for the user's enrollment status which was gained through this workflow. | 
| ..type | enum | Optional | Expiry method. Supported Values: Example: A "Weekend Sale" runs from Friday to Sunday. You opt-in on Friday. Your opt-in status is active until the promotion itself ends on Sunday night. 
 Example: A "7-Day Free Trial." You opt-in by signing up on a Tuesday. Your trial (your opt-in status) lasts for exactly 7 days, expiring next Tuesday. If your friend signs up on Friday, their trial expires next Friday. 
 Example: A "Summer Contest" where you can opt-in anytime. The rules state all entries and opt-in statuses expire on December 31st. If you opt-in on July 1st or December 30th, your status still ends on December 31st. | 
| ..value | integer | Optional | Duration until when the enrollment will be active. | 
| ..expiryDate | string | Optional | The exact date and time enrollment expires. Example: "2025-12-31T23:59:59Z" | 
| optinLimitPerCustomer | Object | Optional | Limits how many times a customer can opt-in. | 
| ..type | enum | Optional | Defines how the limit is set Supported values: 
 
 | 
| ..value | integer | Optional | The maximum number of times. Example: 1 | 
| ..periodType | enum | Conditional | Defines the Window type. Supported Values:  Example: If the limit is "1" per "7" days and you get one on a Wednesday, you can't get another one until the following Wednesday. It's not tied to a calendar week. Required if type is  | 
| ..periodUnit | enum | Conditional | Specifies the interval at which the limit resets. Supported Values: 
 
 
 | 
| maxRedemptionsPerEarnPerCustomer | Object | Optional | Specifies the maximum number of times a customer can redeem rewards that they earn after joining the promotion through this specific workflow. | 
| ..type | enum | Optional | Defines if the redemption limit resets based on a set period. 
 Example: "Limit 1 free welcome gift per customer." Once you get it, you can't get another one, even if you qualify again. 
 Example: "Limit 1 free coffee per day." You can get one on Monday, the limit resets, and you can get another one on Tuesday. | 
| ..value | integer | Optional | The maximum number of redemptions. | 
| ..periodType | enum | Conditional | Defines the type of period at which the redemption limit resets.
Supported Values:  | 
| ..periodUnit | enum | Conditional | Specifies the interval at which the customer can redeem rewards. Supported Values: 
 
 
 Required if type is PERIOD_BASED. | 
| enrolmentLimitPerPromotion | Object | Optional | Defines the overall limit on total enrollments or opt-ins possible through this workflow. | 
| ..type | enum | Optional | Defines if the enrollment limit per promotion resets based on set intervals. 
 Example: "Limit 1 free welcome gift per customer." Once you get the gift, you can't get another one, even if you qualify again. 
 Example: "Limit 1 free coffee per day." You can get one on Monday, the limit resets, and you can get another one on Tuesday. | 
| ..value | integer | Optional | Specifies the maximum enrollment limit per promotion. | 
| ..periodType | enum | Conditional | Defines how the overall limit per promotion is calculated. 
 Example: Imagine the global enrollment limit is 1000, type is     | 
| ..periodUnit | enum | Conditional | Defines the specific time an overall enrollment limit resets per promotion: 
 Example: If the limit is "1,000 enrollments per Day," the system will allow a total of 1,000 customers (from all customers) to enroll on Monday. On Tuesday, the counter resets, and a new 1,000 total enrollments are allowed. 
 Example: If the limit is "1,000 enrollments per Week," the system allows 1,000 total customers to enroll between Sunday and Saturday. The counter then resets for the next week. 
 Example: If the limit is "1,000 enrollments per Month," a total of 1,000 customers can enroll during all of November. The counter then resets on December 1st.
Required if type is  | 
| enrolmentLimitPerCustomer | Object | Optional | Limits how many times one customer can enroll via this workflow. | 
| ..type | enum | Optional | Defines how the limit is applied to a single customer: 
 Example: A "Welcome Offer." You can enroll only one time. Even if you leave the program and come back, you can't enroll in this promotion again. 
 Example: A "Monthly Pass" promotion. The limit is "1 enrollment per Month." You can enroll in January, and then after the limit resets, you can enroll again in February. | 
| ..value | integer | Optional | The maximum number of times a customer can enroll. Example: 1 | 
| ..periodType | enum | Conditional | This defines how the time-based limit is calculated for that specific customer. 
 Example: If the limit is "1 enrollment per WEEKLY period" and a customer enrolls on a Tuesday, their 7-day "moving window" starts. They cannot enroll again until the following Tuesday. | 
| ..periodUnit | enum | Conditional | Defines the specific time unit for the  Supported values: 
 Example: A limit of "1 enrollment per Day." A customer can enroll on Monday, and then the limit resets, allowing them to enroll again on Tuesday. 
 Example: A limit of "1 enrollment per Week." A customer enrolls on Tuesday. They cannot enroll again until the next week (how the week is defined, e.g., Sun-Sat or a rolling 7 days, depends on the periodType). 
 Example: A limit of "1 enrollment per Month." A customer enrolls in November. They cannot enroll again until the limit resets in December. | 
| maxPointsPerEarnPerCustomer | Object | Optional | Defines the maximum points a customer can earn from a single reward activity, after they have enrolled or opted-in through this workflow | 
| ..type | enum | Optional | Defines how often the points limit is applied. 
 Example: The limit is 500 points. -On Tuesday, you make another purchase and earn 700 points. This single action is capped, so you only get 500 points. -On Wednesday, you make a third purchase and earn 400 points (OK, < 500). This limit applies per-action, not over time. 
 Example: The limit is 500 points per DAILY period. -On Monday morning, you earn 300 points (OK). -On Monday afternoon, you earn 400 points. The system checks your total for the day (300 + 400 = 700). Since this exceeds 500, it will only award you the remaining 200 points for this second action. -On Tuesday, the limit resets, and you can earn up to 500 points again. | 
| ..value | integer | Optional | The maximum points that can be earned. | 
| ..periodType | enum | Conditional | Defines how the time-based points limit is calculated. MOVING_WINDOW: The limit is based on a rolling timeframe (e.g., "the last 7 days" or "the last 30 days") that looks backward from the exact moment of the transaction. It is not tied to a fixed calendar (like "this week" or "this month"). Example: The limit is 1000 points per WEEKLY (periodUnit) MOVING_WINDOW. -On Wednesday, Jan 7th, you try to earn 500 points. -The system checks the last 7 days (Jan 1st - Jan 7th), sees you already earned 600, so this new action is capped at 400 points (to reach the 1000-point limit). You must wait until Monday, Jan 12th (when the 600 points from Jan 5th "fall off" the 7-day window) to earn more. | 
| ..periodUnit | enum | Conditional | Defines the specific interval for a  
 Example: A limit of "1 reward per Day." A customer can get the reward on Monday, and then the limit resets, allowing them to get it again on Tuesday. 
 Example: A limit of "1 reward per Week." A customer gets the reward on Tuesday. They cannot get it again until the following week (e.g., the next Sunday or Monday, depending on settings). 
 Example: A limit of "1 reward per Month." A customer gets the reward on November 5th. They cannot get it again until the limit resets on December 1st. | 
Requirement 1: Audience Filter + Activity Opt-In
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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Healthy Habits Wellness Week Opt-In-UI", "description": "Audience enroll (ID 612174375), activity opt-in w/ ALL restrictions.",
        "orgId": 100737, "programId": 2607, "startDate": "2025-11-17T00:00:00+05:30", "endDate": "2025-11-23T23:59:59+05:30",
        "promotionType": "GENERIC", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "HH_WELLNESS_OPTIN_NOV25_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": null, "promotionMetadata": []
    },
    "customerEnrolment": {
        "enrolmentMethod": "AUDIENCE_FILTER",
        "audienceGroups": [
            { "audienceGroupId": 612174375, "audienceGroupName": "Registered", "description": "All registered users" }
        ]
    },
    "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-17", "endDate": "2025-11-23",
                        "actions":[{
                            "id":"temp_action_optin_aaa", "actionName": "EARN_PROMOTION_ACTION",
                            "actionClass":"com.capillary.shopbook.pointsengine.endpoint.impl.action.CommunicationDecoratorActionImpl",
                            "description": "Perform Opt-In",
                            "mandatoryPropertiesValues": {
                                "promotionIdentifier": "HH_WELLNESS_OPTIN_NOV25_UI",
                                "activityName": "Opt-in via Purchase",
                                "delegateActionClass": "com.capillary.shopbook.pointsengine.endpoint.impl.action.EarnPromotionActionImpl"
                            },
                            "mandatoryComplexPropertiesValues": {}, "embeddedStrategies": []
                        }]
                    }],
                    "milestones": [], "cycles": [], "activityCycles": []
                }
            ],
            "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": [], "audienceMapping": [] }
    },
    "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-17", "endDate": "2025-11-23",
                "actions": [{"id":"temp_action_wellness", "actionName":"AWARD_POINTS_ACTION", "actionClass":"...", "mandatoryPropertiesValues":{"AwardStrategy":"109010"}, "embeddedStrategies":[]}]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": []
}'
Requirement 2: Import Enrollment + Audience Enrollment 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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Gadget Galaxy Beta Tester Program Q1-UI", "description": "Import enroll, audience dynamic enroll (ID 612174375) w/ ALL restrictions.",
        "orgId": 100737, "programId": 2607, "startDate": "2026-01-01T00:00:00+05:30", "endDate": "2026-03-31T23:59:59+05:30",
        "promotionType": "GENERIC", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "GG_BETA_Q126_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": null, "promotionMetadata": []
    },
    "customerEnrolment": {
        "enrolmentMethod": "IMPORT",
        "audienceGroups": []
    },
    "workflowMetadata": {
        "optin": { "activities": [], "audienceMapping": [] },
        "enrolment": {
            "basedOn": "AUDIENCE",
            "activities": [],
            "audienceMapping": [
                { "groupId": 612174375, "groupName": "PreOrder List" }
            ],
            "restrictions": {
                "optinExpiryBasedOn": { "type": "CUSTOM", "value": 90 },
                "enrolmentExpiryBasedOn": { "type": "FIXED_DATE", "expiryDate":"2026-03-31T23:59:59Z" },
                "optinLimitPerCustomer": { "value": "1" },
                "maxRedemptionsPerEarnPerCustomer": { "value": "2", "type": "NON_PERIOD_BASED" },
                "enrolmentLimitPerPromotion": { "value": "1000" },
                "enrolmentLimitPerCustomer": { "value": "1", "type": "PERIOD_BASED", "periodType": "MOVING_WINDOW", "periodUnit": "MONTHLY" },
                "maxPointsPerEarnPerCustomer": { "value": 500, "type": "NON_PERIOD_BASED" }
            }
        }
    },
    "activities": [
        {
            "id": "activity_1761xxxxxx05", "type": "SINGLE", "name": "Beta Reward", "event": "FeedbackSubmitted",
            "expJSON": "{\n  \"arity\": \"literal\",\n  \"type\": \"boolean:primitive\",\n  \"value\": \"true\"\n}",
            "commonCycleActionMapping": [{
                "cycle": "Cycle_1", "startDate": "2026-01-01", "endDate": "2026-03-31",
                "actions": [{"id":"temp_action_beta_pts", "actionName":"AWARD_POINTS_ACTION", "actionClass":"...", "mandatoryPropertiesValues":{"AwardStrategy":"109010", "ExpiryStrategy": "109006"}, "embeddedStrategies":[]}]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": []
}'
The activities Object
Defines the core logic of the promotion: the triggers (events and conditions) and the resulting actions (rewards). This is an array, so you can have multiple activity objects.
activities (Common Fields)
These fields are present on all activity objects, whether SINGLE or GROUP.
| Field | Type | Required | Description | 
|---|---|---|---|
| id | string | Optional | Unique identifier for the activity. 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" | 
| refId | string | Optional | External reference ID. Example: "REF001" | 
| parentId | string | Optional | ID of the parent if this is a nested activity inside a GROUP. Example: "activity_group_parent" | 
| rulesetId | string | Optional | Links to a complex external rule set. Example: "ruleset_abc" | 
| 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 | Cycle start date/time (ISO 8601). | 
| ..endDate | string | Optional | Cycle end date/time (ISO 8601). | 
| commonCycleActionMapping | Array (Object) | Optional | Defines the reward(s) for this activity. Links actions to cycles. | 
| ..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 | Specific start date for this action mapping (overrides cycle). | 
| ..endDate | string | Optional | Specific end date for this action mapping (overrides cycle). | 
| ..rulesetId | string | Optional | Specific ruleset just for this action mapping. | 
| ..actions | Array (Object) | Optional | The list of rewards to issue. See Nested: Action Object table below. | 
Nested: Action Object (fields inside actions array)
| Field | Type | Required | Description | 
|---|---|---|---|
| id | string | Optional | Unique ID for the action. Example: "action_award_points_1" | 
| actionName | string | Yes | The type of reward. Example: "AWARD_CURRENCY", "ISSUE_COUPON", "MANAGE_TIER_ACTION". | 
| actionClass | string | Yes | The backend Java class implementing the action. Example: "com.capillary...AwardCurrency" | 
| description | string | Optional | Informational description. Example: "Award 10 base points" | 
| mandatoryPropertiesValues | Object | Conditional | Required properties for the action. Values are strings. Example: {"POINTS_TO_AWARD": "10"} | 
| mandatoryComplexPropertiesValues | Object | Optional | Complex properties where values are JSON objects. Example: { "customConfig": { "nested": true } } | 
| embeddedStrategies | Array (Object) | Optional | Defines strategies (like custom expiry) just for this action. | 
Fields for "SINGLE" Activities
| Field | Type | Required | Description | 
|---|---|---|---|
| event | string | Yes | Specifies the exact event name that triggers this activity. Supported Values: String representing a valid event name (e.g., "TransactionAdd", "CustomerRegistration", "PageView", or a custom event name). Example: "TransactionAdd" | 
| ruleExpression | string | Optional | Specifies the rule expression string (DSL) to filter the triggering event. Supported Values: String conforming to the rule grammar. Example: "transaction.amount > 100 AND transaction.storeId == 10" | 
| expJSON | string | Optional | Specifies the JSON representation of the ruleExpression. Supported Values: Valid JSON rule structure string. Example: "{ "operator": ">", "field": "transaction.amount", "value": 100 }" | 
| frequencyType | string | Optional | Specifies the time unit for milestone evaluation, often used with targetEvaluationType: CYCLIC_WINDOW. - DAILY: The milestone tracks progress in daily blocks (e.g., "visit 3 days this month"). - WEEKLY: The milestone tracks progress in weekly blocks (e.g., "spend $50 for 2 weeks"). - MONTHLY: The milestone tracks progress in monthly blocks (e.g., "earn 1000 points for 3 months"). Supported Values: "DAILY", "WEEKLY", "MONTHLY". Example: "DAILY" | 
| targetEvaluationType | enum | Optional | Specifies the evaluation logic window for milestones. - FIXED_CALENDAR_WINDOW: Uses defined start/end dates for the entire milestone. - CYCLIC_WINDOW: Resets progress based on cycles defined in activityCycles or milestones.periods (used for streaks/weekly goals). - PERIOD_AGNOSTIC_WINDOW: Evaluates over the entire promotion duration without any resets. - CALENDAR_CYCLIC_WINDOW: Combines calendar and cyclic logic. Supported Values: FIXED_CALENDAR_WINDOW, CYCLIC_WINDOW, PERIOD_AGNOSTIC_WINDOW, CALENDAR_CYCLIC_WINDOW. Example: "CYCLIC_WINDOW" | 
| targetCycleStartDate | string (date-time) | Optional | Specifies the start date of the overall target evaluation cycle (used if targetEvaluationType is set). Supported Values: ISO 8601 date-time string. Example: "2025-11-01T00:00:00Z" | 
| targetCycleEndDate | string (date-time) | Optional | Specifies the end date of the overall target evaluation cycle (used if targetEvaluationType is set). Supported Values: ISO 8601 date-time string. Example: "2025-11-30T23:59:59Z" | 
| activityCycles | Array (Object) | Optional | Defines specific, named time periods (cycles) used by a milestone (e.g., "Week 1", "Week 2"). Supported Values: Array of ActivityCycle objects. Example: [ { "id": "ac1", "name": "Weekly Cycle"} ] | 
| ..id | string | Optional | Specifies the activity cycle ID. Supported Values: String ID. Example: "ac1" | 
| ..name | string | Optional | Specifies the activity cycle name. Supported Values: String. Example: "Weekly Cycle" | 
| ..startDate | string | Optional | Specifies the activity cycle start date. Supported Values: String (Date or DateTime format). Example: "2025-11-03" | 
| ..endDate | string | Optional | Specifies the activity cycle end date. Supported Values: String (Date or DateTime format). Example: "2025-11-09" | 
| ..refCode | string | Optional | Specifies the activity cycle reference code. Supported Values: String. Example: "WEEK45" | 
| ..isActive | boolean | Optional | Indicates if the activity cycle is active. Supported Values: true, false. Example: true | 
| milestones | Array (Object) | Optional | Defines a list of target milestones within this activity (Max 1 allowed). Supported Values: Array containing max one Milestone object. Example: [ { "name": "Tier 1", ... } ] | 
| ..name | string | Optional | Specifies the milestone name. Supported Values: String. Example: "Tier 1: Spend $100" | 
| ..sameActionsForEveryCycle | boolean | Optional | Indicates if the same actions apply across all cycles defined for this milestone. Supported Values: true, false. Example: true | 
| ..differentTargetsForEveryCycle | boolean | Optional | Indicates if target values differ across cycles. Supported Values: true, false. Example: false | 
| ..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: String representing tracking type (e.g., "DEFAULT", "STREAKS"). Example: "DEFAULT" | 
| ..targetType | enum | Yes | Defines the KPI to track for the milestone. Supported Values: QUANTITY, SALES, COUNT, VISIT, GROSS_SALES, REGULAR_POINTS, PROMOTIONAL_POINTS, ALL_POINTS, EXTENDED_FIELD, EVENT_ATTRIBUTE, REGULAR, PROMOTIONAL, ALL. Example: "SALES" | 
| ..targetEntity | enum | Yes | Specifies the entity to track the targetType against. Supported Values: TRANSACTION, LINEITEM, POINTS, EVENT, ALTERNATE_CURRENCIES. Example: "TRANSACTION" | 
| ..defaultValue | string | Optional | Specifies the target value threshold for achieving the milestone. Supported Values: String representing a number. Example: "100" | 
| ..targetValue | string | Optional | Specifies the target value to achieve the milestone (often same as defaultValue). Supported Values: String representing a number. Example: "100" | 
| ..preferredTillId | integer (int64) | Optional | Indicates a preferred till ID if tracking is specific to certain POS terminals. Supported Values: Integer till ID. Example: 9876 | 
| ..frequencyType | string | Optional | Specifies the time unit for milestone evaluation, often used with targetEvaluationType: CYCLIC_WINDOW. - DAILY: The milestone tracks progress in daily blocks (e.g., "visit 3 days this month"). - WEEKLY: The milestone tracks progress in weekly blocks (e.g., "spend $50 for 2 weeks"). - MONTHLY: The milestone tracks progress in monthly blocks (e.g., "earn 1000 points for 3 months"). - PROMOTION_DURATION: The milestone tracks progress over the entire promotion duration. Example: "PROMOTION_DURATION" | 
| ..targetEvaluationType | enum | Optional | Specifies the evaluation logic window for milestones. - FIXED_CALENDAR_WINDOW: Uses defined start/end dates for the entire milestone. - CYCLIC_WINDOW: Resets progress based on cycles defined in activityCycles or milestones.periods (used for streaks/weekly goals). - PERIOD_AGNOSTIC_WINDOW: Evaluates over the entire promotion duration without any resets. - CALENDAR_CYCLIC_WINDOW: Combines calendar and cyclic logic. Supported Values: FIXED_CALENDAR_WINDOW, CYCLIC_WINDOW, PERIOD_AGNOSTIC_WINDOW, CALENDAR_CYCLIC_WINDOW. Example: "FIXED_CALENDAR_WINDOW" | 
| ..recurringCycles | integer (int32) | Optional | Specifies the number of recurring cycles for milestone evaluation. Supported Values: Integer. Example: 1 | 
| ..targetGroupId | integer (int64) | Optional | Indicates the target group ID associated with this milestone's tracking logic. Supported Values: Integer target group ID. Example: 112233 | 
| ..leaderboardEnabled | boolean | Optional | Indicates if a leaderboard competition is enabled for this milestone. Supported Values: true, false. Example: false | 
| ..cycleActionMapping | Array (Object) | Optional | Defines the reward(s) for achieving the milestone. (Same structure as commonCycleActionMapping). | 
| ..streaks | Array (Object) | Optional | Defines streak configuration if trackingType is STREAKS. Example: [ { "name": "3 Visits", ... } ] | 
| ....name | string | Optional | Specifies the streak name. Supported Values: String. Example: "3 Consecutive Visits" | 
| ....targetCountOfSequence | integer (int32) | Optional | Specifies the required count within each period (e.g., 1 visit per day). Supported Values: Integer. Example: 1 | 
| ....consecutive | boolean | Optional | true means the streak must be unbroken. false allows for non-consecutive days. Supported Values: true, false. Example: true | 
| ..aggregateFunction | string | Optional | Specifies the function to aggregate values. SUM (for SALES) or COUNT (for VISIT/COUNT). Supported Values: "SUM", "COUNT". Example: "SUM" | 
| ..cycles | Array (Object) | Optional | Defines the evaluation cycles specific to this milestone (alternative to activityCycles). | 
| ....id | string | Optional | Specifies the cycle ID. Supported Values: String ID. Example: "m_cycle_1" | 
| ....name | string | Optional | Specifies the cycle name. Supported Values: String. Example: "Milestone Nov Cycle" | 
| ....startDate | string (date-time) | Optional | Specifies the cycle start date. Supported Values: ISO 8601 date-time string. | 
| ....endDate | string (date-time) | Optional | Specifies the cycle end date. Supported Values: ISO 8601 date-time string. | 
| ..periods | Array (Object) | Optional | Defines the evaluation periods for the milestone (often used for streaks). | 
| ....id | string | Optional | Specifies the period ID. Supported Values: String ID. Example: "m_period_1" | 
| ....name | string | Optional | Specifies the period name. Supported Values: String. Example: "Milestone Nov Period" | 
| ....startDate | string | Optional | Specifies the period start date. Supported Values: String (Date or DateTime format). | 
| ....endDate | string | Optional | Specifies the period end date. Supported Values: String (Date or DateTime format). | 
| ....refCode | string | Optional | Specifies the period reference code. Supported Values: String. | 
| ....isActive | boolean | Optional | Indicates if the period is active. Supported Values: true, false. | 
| ..targetRuleIds | Array (integer int64) | Optional | Indicates associated target rule IDs, potentially linking to more complex backend rules. Supported Values: Array of integer target rule IDs. Example: [ 456, 789 ] | 
| ..individualMilestoneFileDetails | Array (Object) | Optional | Details related to any uploaded files providing individual targets for this milestone. | 
| ....uploadFileName | string | Optional | The original name of the uploaded file. Example: "targets.csv" | 
| ....fileUrl | string | Optional | The system URL where the file is stored. Example: "https://storage.cap/targets.csv" | 
| ....status | string | Optional | The processing status of the file. Example: "PROCESSED" | 
| ....totalRecords | integer | Optional | The total number of records found in the file. Example: 10 | 
| ....successRecords | integer | Optional | The number of records successfully processed. Example: 10 | 
| ....failureCount | integer | Optional | The number of records that failed to process. Example: 0 | 
| Field | Type | Required | Description | 
|---|---|---|---|
| event | string | Yes | Specifies the exact event name that triggers this activity. Supported Values: String representing a valid event name (e.g., "TransactionAdd", "CustomerRegistration", "PageView", or a custom event name). Example: "TransactionAdd" | 
| ruleExpression | string | Optional | Specifies the rule expression string (DSL) to filter the triggering event. Supported Values: String conforming to the rule grammar. Example: "transaction.amount > 100" | 
| expJSON | string | Optional | Specifies the JSON representation of the ruleExpression. Supported Values: Valid JSON rule structure string. Example: "{ "operator": ">", "field": "transaction.amount", "value": 100 }" | 
| frequencyType | string | Optional | Specifies the time unit for milestone evaluation, often used with targetEvaluationType: CYCLIC_WINDOW.<br />- DAILY: The milestone tracks progress in daily blocks (e.g., "visit 3 days this month").<br />- WEEKLY: The milestone tracks progress in weekly blocks (e.g., "spend $50 for 2 weeks").<br />- MONTHLY: The milestone tracks progress in monthly blocks (e.g., "earn 1000 points for 3 months").<br />Example: "DAILY" | 
| targetEvaluationType | enum | Optional | Specifies the evaluation logic window for milestones.<br />- FIXED_CALENDAR_WINDOW: Uses defined start/end dates for the entire milestone.<br />- CYCLIC_WINDOW: Resets progress based on cycles defined in activityCycles or milestones.periods (used for streaks/weekly goals).<br />- PERIOD_AGNOSTIC_WINDOW: Evaluates over the entire promotion duration without any resets.<br />- CALENDAR_CYCLIC_WINDOW: Combines calendar and cyclic logic.<br />Example: "CYCLIC_WINDOW" | 
| targetCycleStartDate | string (date-time) | Optional | Specifies the start date of the overall target evaluation cycle (used if targetEvaluationType is set). Supported Values: ISO 8601 date-time string. Example: "2025-11-01T00:00:00Z" | 
| targetCycleEndDate | string (date-time) | Optional | Specifies the end date of the overall target evaluation cycle (used if targetEvaluationType is set). Supported Values: ISO 8601 date-time string. Example: "2025-11-30T23:59:59Z" | 
| activityCycles | Array (Object) | Optional | Defines cycles specific to this single activity, potentially overriding general cycles (ActivityCycle). Supported Values: Array of ActivityCycle objects. Example: [ { "id": "ac1", "name": "Weekly Cycle"} ] | 
| ..id | string | Optional | Specifies the activity cycle ID. Supported Values: String ID. Example: "ac1" | 
| ..name | string | Optional | Specifies the activity cycle name. Supported Values: String. Example: "Weekly Cycle" | 
| ..startDate | string | Optional | Specifies the activity cycle start date. Supported Values: String (Date or DateTime format). Example: "2025-11-03" | 
| ..endDate | string | Optional | Specifies the activity cycle end date. Supported Values: String (Date or DateTime format). Example: "2025-11-09" | 
| ..refCode | string | Optional | Specifies the activity cycle reference code. Supported Values: String. Example: "WEEK45" | 
| ..isActive | boolean | Optional | Indicates if the activity cycle is active. Supported Values: true, false. Example: true | 
| milestones | Array (Object) | Optional | Defines a list of target milestones within this activity (Max 1 allowed). See Nested: Milestone Object table below. Example: [ { "name": "Tier 1", "targetType": "SALES", ... } ] | 
     Fields for "GROUP" Activities
| Field | Type | Required | Description | 
|---|---|---|---|
| combinationType | enum | Yes | Logic to combine children. Supported Values: ANY, ALL. | 
| children | Array (Object) | Yes | List of nested Activity Objects. | 
| event | string | Optional | Event that applies to the group as a whole. | 
| ruleExpression | string | Optional | Rule expression that applies to the group result. | 
| expJSON | string | Optional | JSON representation of the group's rule expression. | 
Nested: Milestone Object (fields inside milestones array)
| Field | Type | Required | Description | 
|---|---|---|---|
| name | string | Optional | Specifies the milestone name. Supported Values: String. Example: "Tier 1: Spend $100" | 
| sameActionsForEveryCycle | boolean | Optional | Indicates if the same actions apply across all cycles defined for this milestone. Supported Values: true, false. Example: true | 
| differentTargetsForEveryCycle | boolean | Optional | Indicates if target values differ across cycles. Supported Values: true, false. Example: false | 
| 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: String representing tracking type (e.g., "DEFAULT", "STREAKS"). Example: "DEFAULT" | 
| targetType | enum | Yes | Defines the KPI to track for the milestone. Supported Values: QUANTITY, SALES, COUNT, VISIT, GROSS_SALES, REGULAR_POINTS, PROMOTIONAL_POINTS, ALL_POINTS, EXTENDED_FIELD, EVENT_ATTRIBUTE, REGULAR, PROMOTIONAL, ALL. Example: "SALES" | 
| targetEntity | enum | Yes | Specifies the entity to track the targetType against. Supported Values: TRANSACTION, LINEITEM, POINTS, EVENT, ALTERNATE_CURRENCIES. Example: "TRANSACTION" | 
| defaultValue | string | Optional | Specifies the target value threshold for achieving the milestone. Supported Values: String representing a number. Example: "100" | 
| targetValue | string | Optional | Specifies the target value to achieve the milestone (often same as defaultValue). Supported Values: String representing a number. Example: "100" | 
| preferredTillId | integer | Optional | Indicates a preferred till ID if tracking is specific to certain POS terminals. Supported Values: Integer till ID. Example: 9876 | 
| frequencyType | string | Optional | Specifies the frequency type for milestone evaluation. Supported Values: String representing frequency (e.g., "PROMOTION_DURATION", "DAILY", "WEEKLY"). Example: "PROMOTION_DURATION" | 
| targetEvaluationType | enum | Optional | Specifies the evaluation logic window. Supported Values: FIXED_CALENDAR_WINDOW, CYCLIC_WINDOW, PERIOD_AGNOSTIC_WINDOW, CALENDAR_CYCLIC_WINDOW. Example: "FIXED_CALENDAR_WINDOW" | 
| recurringCycles | integer | Optional | Specifies the number of recurring cycles for milestone evaluation. Supported Values: Integer. Example: 1 | 
| targetGroupId | integer | Optional | Indicates the target group ID associated with this milestone's tracking logic. Supported Values: Integer target group ID. Example: 112233 | 
| leaderboardEnabled | boolean | Optional | Indicates if a leaderboard competition is enabled for this milestone. Supported Values: true, false. Example: false | 
| cycleActionMapping | Array (Object) | Optional | Defines the reward(s) for achieving the milestone. (Same structure as commonCycleActionMapping). | 
| streaks | Array (Object) | Optional | Defines streak configuration if trackingType is STREAKS. Example: [ { "name": "3 Visits", ... } ] | 
| ..name | string | Optional | Specifies the streak name. Supported Values: String. Example: "3 Consecutive Visits" | 
| ..targetCountOfSequence | integer | Optional | Specifies the required count within each period (e.g., 1 visit per day). Supported Values: Integer. Example: 1 | 
| ..consecutive | boolean | Optional | true means the streak must be unbroken. false allows for non-consecutive days. Supported Values: true, false. Example: true | 
| aggregateFunction | string | Optional | Specifies the function to aggregate values. SUM (for SALES) or COUNT (for VISIT/COUNT). Supported Values: "SUM", "COUNT". Example: "SUM" | 
| cycles | Array (Object) | Optional | Defines the evaluation cycles specific to this milestone (alternative to activityCycles). | 
| ..id | string | Optional | Specifies the cycle ID. Supported Values: String ID. Example: "m_cycle_1" | 
| ..name | string | Optional | Specifies the cycle name. Supported Values: String. Example: "Milestone Nov Cycle" | 
| ..startDate | string (date-time) | Optional | Specifies the cycle start date. Supported Values: ISO 8601 date-time string. | 
| ..endDate | string (date-time) | Optional | Specifies the cycle end date. Supported Values: ISO 8601 date-time string. | 
| periods | Array (Object) | Optional | Defines the evaluation periods for the milestone (often used for streaks). | 
| ..id | string | Optional | Specifies the period ID. Supported Values: String ID. Example: "m_period_1" | 
| ..name | string | Optional | Specifies the period name. Supported Values: String. Example: "Milestone Nov Period" | 
| ..startDate | string | Optional | Specifies the period start date. Supported Values: String (Date or DateTime format). | 
| ..endDate | string | Optional | Specifies the period end date. Supported Values: String (Date or DateTime format). | 
| ..refCode | string | Optional | Specifies the period reference code. Supported Values: String. | 
| ..isActive | boolean | Optional | Indicates if the period is active. Supported Values: true, false. | 
| individualMilestoneFileDetails | Array (Object) | Optional | Details related to any uploaded files providing individual targets for this milestone. | 
| ..uploadFileName | string | Optional | The original name of the uploaded file. Example: "targets.csv" | 
| ..fileUrl | string | Optional | The system URL where the file is stored. Example: "https://storage.cap/targets.csv" | 
| ..status | string | Optional | The processing status of the file. Example: "PROCESSED" | 
| ..totalRecords | integer | Optional | The total number of records found in the file. Example: 10 | 
| ..successRecords | integer | Optional | The number of records successfully processed. Example: 10 | 
| ..failureCount | integer | Optional | The number of records that failed to process. Example: 0 | 
Requirement 1: Milestone + Rule Expression  + Activity Cycles
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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "FitNation Workout Warrior - Nov-UI", "description": "Milestone: 15 Gym Check-ins in Nov at Loc 101. Reward: Tier Upgrade.",
        "orgId": 100737, "programId": 2607, "startDate": "2025-11-01T00:00:00+05:30", "endDate": "2025-11-30T23:59:59+05:30",
        "promotionType": "GENERIC", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "FN_WARRIOR_NOV25_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": null, "promotionMetadata": []
    },
    "customerEnrolment": { "enrolmentMethod": "TRANSACTION", "audienceGroups": [] },
    "activities": [
        {
            "id": "activity_1761xxxxxx06", "type": "SINGLE", "name": "Track Gym CheckIns", "event": "GymCheckIn",
            "ruleExpression": "event.locationId == 101",
            "frequencyType": "WEEKLY",
            "targetEvaluationType": "CYCLIC_WINDOW",
            "activityCycles": [
                {"id": "ac_w1", "name": "Nov Week 1", "startDate": "2025-11-01", "endDate": "2025-11-09", "refCode":"W1", "isActive": true},
                {"id": "ac_w2", "name": "Nov Week 2", "startDate": "2025-11-10", "endDate": "2025-11-16", "refCode":"W2", "isActive": true},
                {"id": "ac_w3", "name": "Nov Week 3", "startDate": "2025-11-17", "endDate": "2025-11-23", "refCode":"W3", "isActive": true},
                {"id": "ac_w4", "name": "Nov Week 4", "startDate": "2025-11-24", "endDate": "2025-11-30", "refCode":"W4", "isActive": true}
            ],
            "milestones": [
                {
                    "name": "Achieve 15 Check-Ins",
                    "description": "Complete 15 Gym Check-ins at Location 101 during November.",
                    "trackingType": "DEFAULT",
                    "targetType": "VISIT",
                    "targetEntity": "EVENT",
                    "defaultValue": "15",
                    "targetValue": "15",
                    "preferredTillId": null,
                    "frequencyType": "PROMOTION_DURATION",
                    "targetEvaluationType": "CYCLIC_WINDOW",
                    "recurringCycles": 1,
                    "targetGroupId": 112233,
                    "leaderboardEnabled": true,
                    "aggregateFunction": "COUNT",
                    "cycleActionMapping": [
                        {
                            "cycle": "Cycle_1",
                            "startDate": "2025-11-01",
                            "endDate": "2025-11-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": []
                                }
                            ]
                        }
                    ],
                    "streaks": [], "cycles": [],
                    "periods": [],
                    "targetRuleIds": [], "individualMilestoneFileDetails": []
                }
            ],
            "commonCycleActionMapping": [],
            "cycles": []
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Requirement 2: Group (ANY) + Nested Group (ALL) + Ruleset + Cycles
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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Gourmet Galaxy Dinner Special-UI", "description": "Points for Steak OR (Salad AND Bread AND >$30), dinner hours only.",
        "orgId": 100737, "programId": 2607, "startDate": "2025-11-01T00:00:00+05:30", "endDate": "2025-11-30T23:59:59+05:30",
        "promotionType": "LOYALTY_EARNING", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "GG_DINNER_NOV25_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": "DIRECT_EARN", "promotionMetadata": []
    },
    "customerEnrolment": { "enrolmentMethod": "TRANSACTION", "audienceGroups": [] },
    "activities": [
        {
            "id": "group_1761xxxxxx07", "type": "GROUP", "name": "Dinner Special Check (ANY)", "combinationType": "ANY", "event": "TransactionAdd",
            "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_1761xxxxxx08", "parentId": "group_1761xxxxxx07",
                    "name": "Bought Premium Steak", "type": "SINGLE",
                    "expJSON": "{ \"arity\": \"binary_operation\", ... \"value\": \"GG-STK-01\" }",
                    "milestones": [ { "name": "Default Milestone Steak", "trackingType": "DEFAULT", "leaderboardEnabled": false } ],
                    "cycles": [], "activityCycles": [], "commonCycleActionMapping": []
                },
                {
                    "id": "sub_group_1761xxxxxx09", "parentId": "group_1761xxxxxx07",
                    "name": "Side Bundle Check (ALL)", "type": "GROUP", "combinationType": "ALL",
                    "rulesetId": "SIDE_BUNDLE",
                    "expJSON": "{\n  \"arity\": \"literal\",\n  \"type\": \"boolean:primitive\",\n  \"value\": \"true\"\n}",
                    "children": [
                        {
                            "id": "sub_sub_activity_10", "parentId": "sub_group_1761xxxxxx09", "name": "Bought Organic Salad", "type": "SINGLE",
                            "expJSON": "{ \"arity\": \"binary_operation\", ..., \"value\": \"Salad\" }",
                            "milestones": [ { "name": "Default Milestone Salad", "trackingType": "DEFAULT", "leaderboardEnabled": false } ],
                            "cycles": [], "activityCycles": [], "commonCycleActionMapping": []
                        },
                        {
                            "id": "sub_sub_activity_11", "parentId": "sub_group_1761xxxxxx09", "name": "Bought Artisan Bread", "type": "SINGLE",
                            "expJSON": "{ \"arity\": \"binary_operation\", ..., \"value\": \"Bread\" }",
                            "milestones": [ { "name": "Default Milestone Bread", "trackingType": "DEFAULT", "leaderboardEnabled": false } ],
                            "cycles": [], "activityCycles": [], "commonCycleActionMapping": []
                        },
                        {
                            "id": "sub_sub_activity_12", "parentId": "sub_group_1761xxxxxx09", "name": "Transaction > $30", "type": "SINGLE",
                            "expJSON": "{ \"arity\": \"binary_operation\", ..., \"value\": \">\", ... \"value\": \"30\" }",
                            "milestones": [ { "name": "Default Milestone Amount", "trackingType": "DEFAULT", "leaderboardEnabled": false } ],
                            "cycles": [], "activityCycles": [], "commonCycleActionMapping": []
                        }
                    ],
                    "cycles": [], "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":"...",
                            "description":"Award 150 Dinner Special Points",
                            "mandatoryPropertiesValues": {"AwardStrategy":"111728","ExpiryStrategy":"121544"},
                            "mandatoryComplexPropertiesValues": {}, "embeddedStrategies": []
                        }
                    ]
                }
            ]
        }
    ],
    "limits": [], "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Limits Object
Specifies system-enforced limits for issuance and redemption. This is an array, so you can define multiple limit objects.
| Field | Type | Required | Description | 
|---|---|---|---|
| entityScope | enum | Optional | Specifies the scope of the limit. Supported values: 
 Default Values: PROMOTION. | 
| granularity | enum | Optional | Specifies the tracking level for the limit. Supported values: 
 | 
| actionType | enum | Optional | Specifies the action type being limited. This restricts the limit to only apply when a specific type of action occurs. Supported values : 
 
 
 
 
 
 
 
 
 
 | 
| actionSubTypeId | string | Optional | Specifies thelimit to a specific sub-type. | 
| limitType | enum | Optional | Specifies the measure used for limiting. 
 | 
| limitValue | number | Optional | Specifies the maximum allowable value for the limit. 
 | 
| period | Object | Conditional | Defines the reset window. See Nested: period Object table below for full stucture. | 
Nested: period Object
Defines the time window and reset logic for a limit.
| Field | Type | Required | Description | 
|---|---|---|---|
| periodType | enum | Optional | Defines the reset style for the limit. 
 
 | 
| periodUnit | enum | Optional | Specifies the unit of time if periodType is  
 | 
| periodValue | integer | Optional | Specifies the numerical value for the periodUnit | 
| periodStartDay | enum | Optional | Specifies which day the calendar week starts on. Supported Values:  | 
| startDate | string (date-time) | Optional | The exact date/time this limit becomes active. | 
| endDate | string (date-time) | Optional | The exact date and time when this limit becomes inactive. | 
Requirement 1: User Limit (Count, Calendar Week)
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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Fresh Juice Weekly Coupon Limit-UI", "description": "Limit B5G1_JUICE coupon to 2 per user per week (Sun-Sat).",
        "orgId": 100737, "programId": 2607, "startDate": "2025-12-01T00:00:00+05:30", "endDate": "2025-12-31T23:59:59+05:30",
        "promotionType": "GENERIC", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "JUICE_LIMIT_DEC25_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": null, "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-01", "endDate": "2025-12-31",
                "actions": [{
                    "id": "temp_action_b5g1", "actionName": "PE_ISSUE_VOUCHER_ACTION", "actionClass":"...",
                    "mandatoryPropertiesValues": {"VoucherSeriesId": "B5G1_JUICE"}, "embeddedStrategies": []
                }]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [
        {
            "granularity": "USER",
            "actionType": "PE_ISSUE_VOUCHER_ACTION",
            "actionSubTypeId": "B5G1_JUICE",
            "limitType": "COUNT",
            "limitValue": 2,
            "period": {
                "periodType": "FIXED_CALENDAR_WINDOW",
                "periodUnit": "WEEKS",
                "periodValue": 1,
                "periodStartDay": "SUNDAY"
            }
        }
    ],
    "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Requirement 2: Overall Limit (Sum, Moving Window)
Brand Requirement: Global Gadgets (Org 100737, Prog 2607). Limit total Points (SUM) across ALL customers (OVERALL) to 1,000,000 in any 30-day MOVING_WINDOW.
curl --location 'https://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Global Gadgets Points Promo w Overall Limit-UI", "description": "Overall promo limit: Max 1M points total awarded in any 30-day window.",
        "orgId": 100737, "programId": 2607, "startDate": "2026-02-01T00:00:00+05:30", "endDate": "2026-04-30T23:59:59+05:30",
        "promotionType": "LOYALTY_EARNING", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "GG_LIMIT_ROLL_Q126_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": "DIRECT_EARN", "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-01", "endDate": "2026-04-30",
                "actions": [ {
                    "id": "temp_action_pts_lim", "actionName": "AWARD_POINTS_ACTION", "actionClass":"...",
                    "mandatoryPropertiesValues": { "AwardStrategy":"109010", "ExpiryStrategy": "109006", "PointType": "Points" },
                    "embeddedStrategies": []
                } ]
            } ],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [
        {
            "granularity": "OVERALL",
            "actionType": "AWARD_CURRENCY",
            "actionSubTypeId": "Points",
            "limitType": "SUM",
            "limitValue": 1000000,
            "period": {
                "periodType": "MOVING_WINDOW",
                "periodValue": 30,
                "periodUnit": "DAYS"
            }
        }
    ],
    "liabilityOwnerSplitInfo": [],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
The liabilityOwnerSplitInfo Object
Defines how the reward liability (cost) is financially distributed. This is an array, so you can define multiple split objects.
| Field | Type | Required | Description | 
|---|---|---|---|
| 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. 
 | 
| componentType | enum | Optional | Specifies what this liability split is for. 
 | 
| 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. 
 | 
| 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 | 
Requirement 1: Two-Way Split (Program/Program)
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 "HiddenGemDefaultProgram" (ID 181, Org 51174) and the "Diamond" program (ID 229, Org 51174). This cost-sharing rule is active.
curl --location 'https://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Liability Split Check - Prog Prog-UI", "description": "Split liability 50/50 between HiddenGem (181) and Diamond (229) programs.",
        "orgId": 51174, "programId": 181, "startDate": "2025-11-20T00:00:00+05:30", "endDate": "2025-12-31T23:59:59+05:30",
        "promotionType": "LOYALTY_EARNING", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "LIABILITY_SPLIT_PROGPROG_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": "DIRECT_EARN", "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-20", "endDate": "2025-12-31",
                "actions": [ {
                    "id": "temp_action_pts_split", "actionName": "AWARD_POINTS_ACTION", "actionClass":"...",
                    "description": "100 Points", "mandatoryPropertiesValues": { "AwardStrategy":"109010", "ExpiryStrategy": "109436", "PointType":"Main" },
                    "embeddedStrategies": []
                } ]
            } ],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [],
    "liabilityOwnerSplitInfo": [
        {
            "liabilityOwnerId": 181, "componentType": "PROMOTION", "ratio": 50, "isActive": true,
            "liabilityOwnerName": "HiddenGemDefaultProgram", "liabilityOwnerType": "PROGRAM", "orgId": 51174
        },
        {
            "liabilityOwnerId": 229, "componentType": "PROMOTION", "ratio": 50, "isActive": true,
            "liabilityOwnerName": "Diamond", "liabilityOwnerType": "PROGRAM", "orgId": 51174
        }
    ],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
Requirement 2: Program Only (100%)
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://nightly.intouch.capillarytech.com/intouch-api/v3/unifiedPromotions' \
--header 'cookie: ...' \
--header 'content-type: application/json' \
--header 'x-cap-remote-user: 50786981' \
--data '{
    "metadata": {
        "name": "Digital Hub Standard Points - 100 Liability-UI", "description": "Standard points promo, 100% program liability.",
        "orgId": 100737, "programId": 2607, "startDate": "2025-12-01T00:00:00+05:30", "endDate": "2025-12-31T23:59:59+05:30",
        "promotionType": "LOYALTY_EARNING", "status": "DRAFT", "timezoneName": "Asia/Kolkata", "promoIdentifer": "DH_STD_LIAB_DEC25_UI",
        "loyaltyConfigMetaData": { }, "loyaltyEarningType": "DIRECT_EARN", "promotionMetadata": []
    },
    "customerEnrolment": { "enrolmentMethod": "TRANSACTION", "audienceGroups": [] },
    "activities": [
        {
            "id": "activity_1761xxxxxxa6", "type": "SINGLE", "name": "Standard Points", "event": "TransactionAdd",
            "expJSON": "{\n  \"arity\": \"literal\",\n  \"type\": \"boolean:primitive\",\n  \"value\": \"true\"\n}",
            "commonCycleActionMapping": [{
                "cycle": "Cycle_1", "startDate": "2025-12-01", "endDate": "2025-12-31",
                "actions": [{
                    "id": "temp_action_std_pts", "actionName": "AWARD_POINTS_ACTION", "actionClass": "...",
                    "description": "Award Standard Points",
                    "mandatoryPropertiesValues": { "AwardStrategy":"109010", "ExpiryStrategy": "109006" },
                    "embeddedStrategies": []
                }]
            }],
            "milestones": [], "cycles": [], "activityCycles": []
        }
    ],
    "limits": [],
    "liabilityOwnerSplitInfo": [
        {
            "liabilityOwnerId": 2607,
            "componentType": "PROMOTION",
            "ratio": 100,
            "isActive": true,
            "liabilityOwnerName": "Default Program Name",
            "liabilityOwnerType": "PROGRAM",
            "orgId": 100737
        }
    ],
    "workflowMetadata": { "optin": { "activities": [], "audienceMapping": [] }, "enrolment": { "activities": [], "audienceMapping": [] } }
}'
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",
            "promoIdentifer": null,
            "promotionId": 0,
            "createdOn": "2025-10-21T20:43:08+05:30",
            "lastModifiedOn": "2025-10-21T20:43:08+05:30",
            "createdBy": 0,
            "lastModifiedBy": 0,
            "loyaltyEarningType": null,
            "version": null,
            "draftDetails": null,
            "loyaltyConfigMetaData": {
                "isStackable": false,
                "isConsideredForRanking": false,
                "isExclusive": false,
                "isAlwaysApply": false
            },
            "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 body parameters
| Field | Type | Description | 
|---|---|---|
| data | Object | The main data object for the promotion (UnifiedPromotion). | 
| .id | String | Specifies the unique system-generated identifier for the unified promotion. | 
| .metadata | Object | Defines the object containing all metadata for the promotion (MetadataResponse). | 
| ..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) | Specifies the start date and time of the promotion in ISO 8601 format. | 
| ..endDate | String (date-time) | Specifies the end date and time of the promotion in ISO 8601 format. | 
| ..timezoneName | String | Specifies the timezone name for the promotion's schedule. | 
| ..promotionType | String | Specifies the type of promotion (e.g., "LOYALTY", "GENERIC", "DISCOUNT"). | 
| ..status | String | Indicates the current status of the promotion (e.g., DRAFT, ACTIVE). | 
| ..promoIdentifer | String | Specifies a unique string identifier for the promotion (may be system-generated). | 
| ..promotionId | Integer (int32) | Specifies the legacy numerical promotion ID (system assigned). | 
| ..createdOn | String (date-time) | Specifies the creation timestamp (system-set). | 
| ..lastModifiedOn | String (date-time) | Specifies the last modification timestamp (system-set). | 
| ..createdBy | Integer (int32) | Specifies the user ID of the creator (system-set). | 
| ..lastModifiedBy | Integer (int32) | Specifies the user ID of the last modifier (system-set). | 
| ..loyaltyEarningType | String | Indicates the loyalty earning type (e.g., DIRECT_EARN, ISSUE_AND_EARN, null). | 
| ..version | String | Specifies the version string of the promotion (system managed). | 
| ..draftDetails | Object | Defines details if the promotion is a draft (DraftDetails). | 
| ...id | String | Specifies the draft's unique ID. | 
| ...status | String | Specifies the draft's status. | 
| ...version | Integer (int32) | Specifies the draft version number. | 
| ...lastModifiedBy | Integer (int32) | Specifies the user who last modified the draft. | 
| ...lastModifiedOn | String (date-time) | Specifies when the draft was last modified. | 
| ..loyaltyConfigMetaData | Object | Defines loyalty-specific configurations (LoyaltyConfigMetaDto). | 
| ...isStackable | Boolean | Indicates if the promotion is stackable. | 
| ...isConsideredForRanking | Boolean | Indicates if the promotion is considered for ranking. | 
| ...isExclusive | Boolean | Indicates if the promotion is exclusive. | 
| ...isAlwaysApply | Boolean | Indicates if the promotion should always apply. | 
| ...skipEarnedDateCheckOnRedeem | Boolean | Indicates if the earned date check should be skipped on redemption. | 
| ..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 common strategies, like expiry (CommonStrategies). | 
| ...expiry | Array (Object) | Defines a list of expiry strategies (StrategyInfo). | 
| ....strategyTypeId | Integer (int32) | Specifies the strategy type ID. | 
| ....propertyValues | String | Specifies the property values for the strategy. | 
| ....owner | String | Specifies the owner of the strategy. | 
| ....updatedViaNewUI | Boolean | Indicates if the strategy was updated via the new UI. | 
| ....useCommonExpiryStrategy | Boolean | Indicates if the common expiry strategy is used. | 
| ....strategyRef | String | Specifies the strategy reference. | 
| ....strategySubType | String | Indicates the strategy sub-type (e.g., ROLLING_EXPIRY_STRATEGY). | 
| ..promotionMode | String | Indicates the promotion mode (e.g., LEGACY, UNIFIED). | 
| .customerEnrolment | Object | Defines the customer enrolment rules (CustomerEnrolment). | 
| ..enrolmentMethod | String | Indicates the method of customer enrolment (e.g., TRANSACTION, IMPORT, AUDIENCE_FILTER). | 
| ..audienceGroups | Array (Object) | Defines a list of audience groups for enrolment (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 (SingleActivity or GroupActivity). | 
| ..id | String | Specifies the unique ID for the activity. | 
| ..type | String | Specifies the type of the activity (SINGLE or GROUP). | 
| ..name | String | Specifies the name of the activity. | 
| ..refId | String | Specifies the reference ID for the activity. | 
| ..parentId | String | Specifies the parent activity's ID (if nested in a group). | 
| ..rulesetId | String | Specifies the ruleset ID for the activity. | 
| ..cycles | Array (Object) | Defines a list of general cycles (Cycle). | 
| ...id | string | Specifies the cycle ID. | 
| ...name | string | Specifies the cycle name. | 
| ...startDate | string (date-time) | Specifies the cycle start date. | 
| ...endDate | string (date-time) | Specifies the cycle end date. | 
| ..commonCycleActionMapping | Array (Object) | Defines action mappings for common cycles (CycleActionMapping). | 
| ...cycle | String | Specifies the cycle name/ID. | 
| ...defaultValue | Number (double) | Specifies the default value for the action. | 
| ...startDate | String (date-time) | Specifies the cycle mapping start date. | 
| ...endDate | String (date-time) | Specifies the cycle mapping end date. | 
| ...rulesetId | String | Specifies the cycle mapping ruleset ID. | 
| ...actions | Array (Object) | Defines a list of actions (Action). | 
| ....id | String | Specifies the action ID. | 
| ....actionName | String | Specifies the action name (e.g., AWARD_POINTS_ACTION). | 
| ....actionClass | String | Specifies the action class. | 
| ....description | String | Specifies the action description. | 
| ....mandatoryPropertiesValues | Object | Defines key-value pairs for mandatory properties. | 
| ....mandatoryComplexPropertiesValues | Object | Defines key-value pairs for mandatory complex properties. | 
| ....embeddedStrategies | Array (Object) | Defines a list of embedded StrategyInfo objects. | 
| ..event | String | (SingleActivity) Specifies the event associated with the activity. | 
| ..ruleExpression | String | (SingleActivity/GroupActivity) Specifies the rule expression. | 
| ..expJSON | String | (SingleActivity/GroupActivity) Specifies the rule expression in JSON format. | 
| ..frequencyType | String | (SingleActivity) Specifies the frequency type. | 
| ..targetEvaluationType | String | (SingleActivity) Specifies the target evaluation type (e.g., CYCLIC_WINDOW). | 
| ..targetCycleStartDate | String (date-time) | (SingleActivity) Specifies the target cycle start date. | 
| ..targetCycleEndDate | String (date-time) | (SingleActivity) Specifies the target cycle end date. | 
| ..activityCycles | Array (Object) | (SingleActivity) Defines activity-specific cycles (ActivityCycle). | 
| ...id | string | Specifies the activity cycle ID. | 
| ...name | string | Specifies the activity cycle name. | 
| ...startDate | string | Specifies the activity cycle start date. | 
| ...endDate | string | Specifies the activity cycle end date. | 
| ...refCode | string | Specifies the activity cycle reference code. | 
| ...isActive | boolean | Indicates if the activity cycle is active. | 
| ..milestones | Array (Object) | (SingleActivity) Defines milestones (Milestone). | 
| ...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 (e.g., DEFAULT, STREAKS). | 
| ...targetType | enum | Defines the KPI to track (e.g., SALES, COUNT, VISIT). | 
| ...targetEntity | enum | Specifies the entity to track against (e.g., TRANSACTION, LINEITEM). | 
| ...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 (e.g., PROMOTION_DURATION). | 
| ...targetEvaluationType | enum | Specifies the evaluation logic window (e.g., FIXED_CALENDAR_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. (Repeats commonCycleActionMapping structure). | 
| ...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 (e.g., SUM, COUNT). | 
| ...cycles | Array (Object) | Defines the evaluation cycles specific to this milestone. (Repeats cycles structure). | 
| ...periods | Array (Object) | Defines the periods for the milestone. (Repeats activityCycles structure). | 
| ...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 (system populated). | 
| ..combinationType | String | (GroupActivity) Indicates how child activities are combined (e.g., ANY, ALL). | 
| ..children | Array (Object) | (GroupActivity) Defines a nested list 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 (ParentDetails). | 
| ..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) | Specifies when the parent was last modified. | 
| .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 (e.g., PROGRAM, PROMOTION). | 
| ..granularity | String | Indicates the granularity of the limit (e.g., OVERALL, USER). | 
| ..entityId | Integer (int64) | Specifies the entity ID the limit applies to. | 
| ..actionType | String | Indicates the action type being limited (e.g., AWARD_CURRENCY). | 
| ..actionSubTypeId | String | Specifies the action sub-type ID (e.g., POINTS). | 
| ..limitType | String | Indicates the type of limit (e.g., SUM, COUNT). | 
| ..limitValue | Number | Specifies the value of the limit. | 
| ..period | Object | Defines the time period for the limit (LimitPeriodResponse). | 
| ...id | Integer (int64) | Specifies the period ID (system-assigned). | 
| ...periodType | String | Indicates the type of period (e.g., NON_PERIOD_BASED). | 
| ...periodUnit | String | Indicates the unit for the period (e.g., DAYS, WEEKS, MONTHS). | 
| ...periodValue | Integer (int32) | Specifies the value for the period. | 
| ...periodStartDay | String | Indicates the start day for weekly periods (e.g., SUNDAY). | 
| ...startDate | String (date-time) | Specifies the fixed start date for the period. | 
| ...endDate | String (date-time) | Specifies the fixed end date for the period. | 
| ..createdOn | String (date-time) | Specifies the creation timestamp of the limit. | 
| ..createdBy | Integer (int64) | Specifies the user ID of the limit creator. | 
| ..lastUpdatedOn | String (date-time) | Specifies the last update timestamp of the limit. | 
| ..lastUpdatedBy | Integer (int64) | Specifies the user ID of the last updater. | 
| ..active | Boolean | Indicates if the limit is active. | 
| .liabilityOwnerSplitInfo | Array (Object) | Defines how liability is split (LiabilityOwnerSplitInfo). | 
| ..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 (e.g., PROGRAM, PROMOTION). | 
| ..createdBy | Integer (int32) | Specifies the user ID of the creator. | 
| ..ratio | Number (double) | Specifies the liability split ratio (0-100). | 
| ..liabilityOwnerName | String | Specifies the liability owner's name. | 
| ..liabilityOwnerType | String | Indicates the liability owner's type (e.g., PARTNER, PROGRAM). | 
| ..active | Boolean | Indicates if the split info is active. | 
| .workflowMetadata | Object | Defines workflow metadata for enrolment and opt-in (WorkflowMetadata). | 
| ..enrolment | Object | Defines enrolment workflow details (EnrolmentResponse). | 
| ...basedOn | String | Indicates the basis for enrolment (e.g., ACTIVITY, AUDIENCE). | 
| ...activities | Array (Object) | Defines activities triggering enrolment. | 
| ...audienceMapping | Array (Object) | Defines audience mappings for enrolment. | 
| ....groupId | Integer (int64) | Specifies the group ID. | 
| ....groupName | String | Specifies the group name. | 
| ...restrictions | Object | Defines enrolment restrictions (PromotionRestrictionsResponse). | 
| ....optinExpiryBasedOn | Object | Defines opt-in expiry (PromotionExpiryConfigResponse). | 
| .....value | Integer (int32) | Specifies the expiry value. | 
| .....expiryDate | String (date-time) | Specifies the expiry date. | 
| .....type | String | Specifies the expiry type. | 
| ....enrolmentExpiryBasedOn | Object | Defines enrolment expiry (PromotionExpiryConfigResponse). | 
| .....value | Integer (int32) | Specifies the expiry value. | 
| .....expiryDate | String (date-time) | Specifies the expiry date. | 
| .....type | String | Specifies the expiry type. | 
| ....optinLimitPerCustomer | Object | Defines opt-in limit (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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 enrolment limit per customer (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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 (OptinResponse). | 
| ...basedOn | String | Indicates the basis for opt-in. | 
| ...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 (PromotionRestrictionsResponse). | 
| ....optinExpiryBasedOn | Object | Defines opt-in expiry (PromotionExpiryConfigResponse). | 
| .....value | Integer (int32) | Specifies the expiry value. | 
| .....expiryDate | String (date-time) | Specifies the expiry date. | 
| .....type | String | Specifies the expiry type. | 
| ....enrolmentExpiryBasedOn | Object | Defines enrolment expiry (PromotionExpiryConfigResponse). | 
| .....value | Integer (int32) | Specifies the expiry value. | 
| .....expiryDate | String (date-time) | Specifies the expiry date. | 
| .....type | String | Specifies the expiry type. | 
| ....optinLimitPerCustomer | Object | Defines opt-in limit (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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 enrolment limit per customer (PromotionRestrictionsConfigResponse). | 
| .....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 (PromotionRestrictionsConfigResponse). | 
| .....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. | 
| .communicationApprovalStatus | Object | Defines the status of communication approval (BulkClaimApproveResponse). | 
| ..success | Boolean | Indicates if the approval status check was successful. | 
| ..message | String | Specifies the status message. | 
| ..response | Object | Defines the nested response object. | 
| ..statusCode | Integer (int32) | Specifies the status code. | 
| errors | Array (Object) | Defines a list of errors that occurred, if any (ApiError). | 
| .code | Integer (int64) | Specifies the error code. | 
| .message | String | Specifies the error message. | 
| warnings | Array (Object) | Defines a list of warnings, if any (ApiWarning). | 
| .message | String | Specifies the warning message. | 
