Update an existing loyalty benefit.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Update Benefit
Updates a loyalty benefit, identified by its loyaltyBenefitId. Send the full benefit definition; the fields you send replace the stored values.
How the update behaves depends on the benefit's current status:
- DRAFT benefit: the draft is updated in place and its
versionincrements. - LIVE benefit: the update forks a new
DRAFTversion under the sameloyaltyBenefitId, withversionreset to0. The forked draft keeps the parent'sbenefitIdentifierandloyaltyBenefitRecordId. The parentLIVErecord stays live and unchanged, and gains ametadata.draftDetailsobject pointing to the in-progress draft. Submit and approve the draft through the workflow to publish your changes.
Once a draft fork exists, Get Benefit still returns the published LIVE version by default. Pass status=DRAFT to retrieve the in-progress draft fork instead.
Example request
curl -L -g -X PUT 'https://eu.api.capillarytech.com/v3/benefits/{{loyaltyBenefitId}}' \
-H 'Content-Type: application/json' \
-H 'Authorization: {{auth}}' \
-H 'X-CAP-API-AUTH-ORG-ID: {{orgId}}' \
-d '{
"name": "Birthday bonus — updated",
"description": "Extra points on birthday month",
"programId": "2352",
"expiryType": "CUSTOM",
"startDate": "2026-08-01T00:00:00-06:00",
"endDate": "2027-01-31T23:59:59-06:00",
"timezoneName": "Asia/Kolkata",
"tierIds": [
8159,
8165,
8166,
10545,
10656
],
"optin": {
"optInStartDate": "2026-08-01T09:00:00-06:00",
"optInEndDate": "2027-01-31T18:00:00-06:00"
},
"activities": [
{
"type": "SINGLE",
"event": "TransactionAdd"
}
]
}'Prerequisites
- Authentication: Basic auth or OAuth token with loyalty program management permissions.
- The benefit must exist.
- The tiers listed in
tierIdsmust exist in the program.
Resource information
| HTTP method | PUT |
|---|---|
| Authentication | Basic or OAuth |
| Pagination supported? | NO |
| Rate limit | YES |
| Batch support | NO |
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
loyaltyBenefitId | string | Required | Unique ID of the benefit to update, returned by Create Benefit. |
Body parameters
API Quick Reference
Benefit
├── name (string)
├── description (string)
├── programId (string)
├── expiryType (enum)
├── startDate (string)
├── endDate (string)
├── timezoneName (string)
├── tierIds[] (integer)
├── optin
│ ├── optInStartDate (string)
│ └── optInEndDate (string)
└── activities[]
├── type (enum)
└── event (string)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Required | Display name of the benefit. Max 255 characters. |
description | string | Required | Description of the benefit. Max 1000 characters. |
programId | string | Required | Loyalty program ID the benefit belongs to, passed as a string (for example, "973"). To retrieve the programId, use the Get Loyalty Programs API. |
expiryType | enum | Required | How the benefit's validity ends. Case-sensitive. CUSTOM requires endDate. INDEFINITE sets a far-future end date automatically. Supported values: CUSTOM, INDEFINITE. |
startDate | string | Required | Defines the benefit's start date and time in ISO 8601 format with the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30Returned unchanged in the response, in the offset you send. |
endDate | string | Conditional | Defines the benefit's end date and time in ISO 8601 format with the region offset. For example: The end date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30Required when expiryType is CUSTOM. Omit it for INDEFINITE. |
timezoneName | string | Required | IANA time zone name for the benefit (for example, Asia/Kolkata). Use timezoneName (lowercase z) — this is the correct field name across Capillary APIs. |
tierIds | array (integer) | Required | Tier IDs the benefit applies to. Each tier must exist in the program. Retrieve tier IDs with the List All Tiers API. |
optin | object | Optional | Object containing the opt-in window during which customers can opt in to the benefit. |
.optInStartDate | string | Optional | Defines the opt-in window's start date and time in ISO 8601 format with the region offset. For example: The start date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30 |
.optInEndDate | string | Optional | Defines the opt-in window's end date and time in ISO 8601 format with the region offset. For example: The end date is at 14:30:45 on December 16, 2025, in India Format for the request parameter: 2025-12-16T14:30:45+05:30 |
activities | array (object) | Required | Activities that the benefit applies to. |
.type | enum | Required | Activity type. Case-sensitive. Supported values: SINGLE. |
.event | string | Required | Event that triggers the activity (for example, TransactionAdd). |
Example response
This example shows the response when you update a DRAFT benefit in place. The draft is updated under the same loyaltyBenefitId and its version increments. The benefit stays in DRAFT status, and benefitIdentifier and loyaltyBenefitRecordId stay null until it's approved. Updating a LIVE benefit instead returns a new DRAFT fork with version reset to 0 and the parent's benefitIdentifier and loyaltyBenefitRecordId retained.
{
"data": {
"loyaltyBenefitId": "86c29c3653f74c0a9f1b2c3d4e5f6a7b",
"version": 1,
"metadata": {
"name": "Birthday bonus",
"description": "Extra points on birthday month",
"programId": "973",
"orgId": 12345,
"expiryType": "CUSTOM",
"status": "DRAFT",
"customerEligibilityType": null,
"benefitIdentifier": null,
"loyaltyBenefitRecordId": null,
"startDate": "2026-08-01T00:00:00+05:30",
"endDate": "2027-01-31T23:59:59+05:30",
"timezoneName": "Asia/Kolkata",
"createdOn": "2026-06-23T14:32:24+05:30",
"lastModifiedOn": "2026-06-23T14:37:35+05:30",
"createdBy": 123456,
"lastModifiedBy": 123456,
"draftDetails": null
},
"benefitCategoryId": -1,
"tierIds": [8159, 8165],
"optin": {
"basedOn": null,
"audienceMapping": null,
"activities": null,
"restrictions": null,
"optInStartDate": "2026-08-01T09:00:00+05:30",
"optInEndDate": "2027-01-31T18:00:00+05:30"
},
"activities": [
{
"type": "SINGLE",
"event": "TransactionAdd",
"allCycles": []
}
],
"limits": null,
"configAttributes": null,
"liabilityOwnerSplitInfo": null,
"workflowMetadata": null,
"communicationApprovalStatus": null,
"parentId": null,
"parentDetails": null,
"comments": null,
"id": "6a3a4ba0c1d2e3f4a5b6c7d8"
},
"errors": null,
"warnings": null
}Response parameters
| Field | Type | Description |
|---|---|---|
data | object | Object containing the updated benefit. For a LIVE benefit, this is the new DRAFT fork. |
.loyaltyBenefitId | string | Unique ID of the benefit. The draft fork shares the same ID as the parent benefit. |
.version | integer | Version number of the benefit. Increments on an in-place draft update. Reset to 0 on a new draft fork of a LIVE benefit. |
.metadata | object | Object containing the benefit's core attributes and audit details. |
..name | string | Display name of the benefit. |
..description | string | Description of the benefit. |
..programId | string | Loyalty program ID the benefit belongs to. |
..orgId | integer | Org ID derived from the auth token. |
..expiryType | enum | How the benefit's validity ends. Possible values: CUSTOM, INDEFINITE. |
..status | enum | Current stage of the benefit lifecycle. DRAFT after a draft fork of a LIVE benefit. Possible values: DRAFT, PENDING_APPROVAL, LIVE, UPCOMING, PAUSED, STOPPED. |
..customerEligibilityType | string | Customer eligibility configuration. null unless advanced eligibility is set up. |
..benefitIdentifier | string | Identifier carried over from the parent benefit on a draft fork. null while a benefit is in DRAFT or PENDING_APPROVAL and has never been approved. |
..loyaltyBenefitRecordId | integer | Record ID carried over from the parent benefit on a draft fork. null while a benefit is in DRAFT or PENDING_APPROVAL and has never been approved. |
..startDate | string | Date and time when the benefit starts, in ISO 8601 format. Returned in the offset you sent. |
..endDate | string | Date and time when the benefit ends, in ISO 8601 format. For INDEFINITE benefits, set to a far-future date automatically. |
..timezoneName | string | IANA time zone name, as sent. |
..createdOn | timestamp | Indicates the date and time the benefit was created, in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC)India server example (real capture from this environment): 2026-06-23T14:32:24+05:30 → 23 June 2026, 14:32:24 (IST)Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
..lastModifiedOn | timestamp | Indicates the date and time the benefit was last modified, in ISO 8601 format, returned in the server time zone. EU server example: 2025-12-16T14:30:45Z → 16 December 2025, 14:30:45 (UTC)India server example (real capture from this environment): 2026-06-23T14:37:35+05:30 → 23 June 2026, 14:37:35 (IST)Note: The response time zone always matches the server time zone, regardless of the time zone offset in the request. |
..createdBy | integer | Till ID of the person who created the benefit. Retrieve till IDs with the Get Active Tills API. |
..lastModifiedBy | integer | Till ID of the person who last modified the benefit. Retrieve till IDs with the Get Active Tills API. |
..draftDetails | object | Object containing details of an in-progress draft when a LIVE benefit has an edit underway. Set on the parent LIVE record after an update; null on a DRAFT in-place update and on the draft fork itself. |
.benefitCategoryId | integer | Benefit category ID. -1 means no benefit category is assigned. |
.tierIds | array | Tier IDs the benefit applies to. |
.optin | object | Object containing the opt-in window, as sent. null if no opt-in window was configured. |
..basedOn | string | Opt-in basis. null unless configured. |
..audienceMapping | object | Object containing the opt-in's audience mapping. null unless configured. |
..activities | array | Activities scoped to the opt-in. null unless configured. |
..restrictions | object | Object containing the opt-in's restrictions. null unless configured. |
..optInStartDate | string | Date and time when the opt-in window opens, in ISO 8601 format. |
..optInEndDate | string | Date and time when the opt-in window closes, in ISO 8601 format. |
.activities | array | Activities the benefit applies to. |
..type | enum | Activity type. Possible values: SINGLE. |
..event | string | Event that triggers the activity. |
..allCycles | array | Cycle entries computed for the activity. |
.limits | array | Usage limits configured for the benefit. null or empty unless limits are configured. |
.configAttributes | object | Object containing advanced configuration attributes. null unless configured. |
.liabilityOwnerSplitInfo | array | Liability split configuration entries. Each entry defines how liability for the benefit is split. null unless configured. See Get Benefit for entry fields. |
.workflowMetadata | object | Object containing additional workflow data. null unless configured. |
.communicationApprovalStatus | object | Object containing the communication approval result. null until the benefit is approved. |
.parentId | string | ID of the parent benefit, when this benefit is a draft fork of a LIVE benefit. null otherwise. |
.parentDetails | object | Object containing details of the parent benefit. null otherwise. |
.comments | string | Reviewer's note from the most recent workflow action. null until reviewed. |
.id | string | Unique ID of this benefit record. A draft fork has its own record ID, distinct from the parent. |
errors | array | Error list. null on success. |
warnings | array | Warning list. null on success. |
Error & warning codes
| Code | Type | Description |
|---|---|---|
loyaltyBenefitId=<id> | Error | No benefit matches the given loyaltyBenefitId. HTTP 404. |
LOYALTY_BENEFITS.NAME_REQUIRED | Error | name is missing. HTTP 400. |
LOYALTY_BENEFITS.DESCRIPTION_REQUIRED | Error | description is missing. HTTP 400. |
LOYALTY_BENEFITS.PROGRAM_ID_REQUIRED | Error | programId is missing. HTTP 400. |
LOYALTY_BENEFITS.END_DATE_REQUIRED_FOR_CUSTOM | Error | expiryType is CUSTOM but endDate is missing. HTTP 400. |
INVALID_EXPIRYTYPE | Error | expiryType is not INDEFINITE or CUSTOM. HTTP 400. |
LOYALTY_BENEFITS.TIER_NOT_FOUND | Error | One or more IDs in tierIds don't exist in the program. HTTP 400. |
Note: Validation errors return a generic numeric code on the wire rather than an error-specific number. The Code column shows the stable symbolic code carried in the error message.
400Validation error: see the error table in the doc page
401Authentication failed
404No benefit matches the given loyaltyBenefitId
