| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Create Tier
Creates a new tier in DRAFT status for a loyalty program. The tier enters a maker-checker approval workflow: submit it with Submit Tier for Approval and publish it with Approve or Reject Tier before it becomes ACTIVE. A program can have up to 50 tiers and only one in-progress DRAFT at a time.
Example request
curl -X POST "https://eu.intouch.capillarytech.com/v3/tiers" \
-H "Authorization: Basic <base64-encoded-credentials>" \
-H "Content-Type: application/json" \
-d '{
"programId": 973,
"name": "Platinum",
"description": "Premium tier for top spenders",
"color": "#E5E4E2",
"eligibility": {
"kpiType": "CURRENT_POINTS",
"threshold": 75000,
"upgradeType": "LAZY"
},
"validity": {
"periodType": "SLAB_UPGRADE",
"periodValue": 12,
"unit": "NUM_MONTHS"
}
}'Prerequisites
- Authentication: Basic auth or OAuth token with loyalty program management permissions.
- The program must have
SLAB_UPGRADEandSLAB_DOWNGRADEstrategies configured. If either is missing, configure them with the program-level Tier Advanced Settings endpoint (POST /programs/{programId}/updateTierAdvancedSettings) before creating tiers.
Header information
| Header | Required | Description |
|---|---|---|
Idempotency-Key | Optional | Unique key to safely retry the request without creating duplicate tiers. |
Body parameters
API quick reference
Tier
├── programId (integer)
├── name (string)
├── description (string)
├── color (string)
├── eligibility
│ ├── kpiType (enum)
│ ├── threshold (number)
│ ├── upgradeType (enum)
│ ├── expressionRelation (enum)
│ └── conditions[]
│ ├── type (enum)
│ ├── value (string)
│ ├── trackerName (string)
│ ├── trackerId (integer)
│ └── trackerCondition (integer)
└── validity
├── periodType (enum)
├── periodValue (integer)
├── unit (string)
├── startDate (string)
├── isFixedTypeWithoutYear (boolean)
├── renewalWindowType (enum)
├── computationWindowStartValue (integer)
├── computationWindowEndValue (integer)
├── minimumDuration (integer)
└── renewal
├── criteriaType (string)
├── downgradeTo (enum)
├── shouldDowngrade (boolean)
├── expressionRelationAIRA (string)
├── expressionRelation (string)
└── conditions
├── purchase (string)
├── numVisits (string)
├── points (string)
└── tracker[]
├── trackerName (string)
├── value (string)
├── trackerId (integer)
└── trackerCondition (integer)
| Field | Type | Required | Description |
|---|---|---|---|
programId | integer | Required | Loyalty program ID the tier belongs to. Must not be -1. |
name | string | Required | Tier name. Max 50 characters. Must be unique among live tiers in the program (case-insensitive). |
description | string | Optional | Tier description. Max 500 characters. |
color | string | Optional | Display color in hex format #RRGGBB (for example, #E5E4E2). |
eligibility | object | Optional | Object containing the conditions a customer must meet to enter this tier. |
.kpiType | enum | Optional | KPI the threshold is measured against. Must be one of: CURRENT_POINTS, CUMULATIVE_POINTS, CUMULATIVE_PURCHASES, TRACKER_VALUE_BASED. Case-sensitive. Must be compatible with the program's KPI type. |
.threshold | number | Optional | KPI value at which a customer upgrades into this tier. Between 0 and 2,147,483,647. Must be greater than the previous tier's threshold. |
.upgradeType | enum | Optional | When tier upgrades are evaluated. Must be one of: EAGER, DYNAMIC, LAZY. Case-sensitive. Must match the program's slab upgrade mode. |
.expressionRelation | enum | Optional | How multiple eligibility conditions combine. Must be one of: AND, OR. Case-sensitive. |
.conditions | array | Optional | Additional eligibility conditions. |
..type | enum | Optional | Condition type. Must be one of: PURCHASE, VISITS, POINTS, TRACKER. Case-sensitive. |
..value | string | Optional | Condition threshold value. |
..trackerName | string | Optional | Tracker display name. Applicable only when type is TRACKER. |
..trackerId | integer | Conditional | Engine tracker instance ID. Required when type is TRACKER. |
..trackerCondition | integer | Conditional | Engine tracker-definition ID. Required when type is TRACKER. |
validity | object | Optional | Object containing the validity period and renewal configuration for the tier. |
.periodType | enum | Optional | How the tier validity period is anchored. Must be one of: FIXED, SLAB_UPGRADE, SLAB_UPGRADE_CYCLIC, FIXED_CUSTOMER_REGISTRATION. Case-sensitive. |
.periodValue | integer | Conditional | Tier duration in months. Required and must be greater than 0 when periodType is FIXED. Defaults to 12 when isFixedTypeWithoutYear is true and the value is omitted. Ignored for FIXED_CUSTOMER_REGISTRATION. |
.unit | string | Optional | Unit of periodValue. Must be NUM_MONTHS. |
.startDate | string | Conditional | Validity anchor date in ISO 8601 format. Applicable for FIXED period types. Must not be sent when periodType is SLAB_UPGRADE or SLAB_UPGRADE_CYCLIC. Must fall on the first day of the month when renewal.shouldDowngrade is true and daily downgrade is off at the program level. |
.isFixedTypeWithoutYear | boolean | Optional | When true, the engine treats startDate as a recurring day-month anchor and ignores the year. |
.renewalWindowType | enum | Optional | How the renewal evaluation window is interpreted. Must be one of: FIXED_DATE_BASED, LAST_CALENDAR_YEAR, CUSTOM_PERIOD. Case-sensitive. Allowed only when periodType is FIXED. |
.computationWindowStartValue | integer | Conditional | Months-back offset for the start of the renewal evaluation window. Must be 0 or greater. Requires renewalWindowType. Between 1 and 36 when renewalWindowType is FIXED_DATE_BASED. Must not be sent when renewalWindowType is LAST_CALENDAR_YEAR. |
.computationWindowEndValue | integer | Conditional | Months-back offset for the end of the renewal evaluation window. Must be 0 or greater. Requires renewalWindowType. For CUSTOM_PERIOD, the difference between start and end values must be 35 or less. Must not be sent when renewalWindowType is LAST_CALENDAR_YEAR. |
.minimumDuration | integer | Optional | Minimum tier duration in months. Must be 0 or greater. The engine doesn't downgrade a customer before this duration elapses. |
.renewal | object | Optional | Object containing the renewal trigger configuration for the tier. |
..criteriaType | string | Optional | Renewal criteria type. Must be exactly Same as eligibility. |
..downgradeTo | enum | Optional | Tier the customer moves to on downgrade. Must be one of: SINGLE, THRESHOLD, LOWEST. Case-sensitive. |
..shouldDowngrade | boolean | Optional | When false, customers in this tier never auto-downgrade. |
..expressionRelationAIRA | string | Optional | Logical expression that combines the renewal conditions, in disjunctive normal form (DNF): groups of conditions joined with AND, with the groups joined by OR, for example (1 AND 2) OR 3, where each number refers to a condition. You can also pass the shortcuts ANYn or ALL. When both expression fields are set, expressionRelation applies. |
..expressionRelation | string | Optional | Logical expression that combines the renewal conditions, in the format used by tiers configured outside this API. Applied as sent. |
..conditions | object | Optional | Object containing the renewal trigger conditions. |
...purchase | string | Optional | Cumulative purchase threshold, passed as a string (for example, "5000"). |
...numVisits | string | Optional | Cumulative visits threshold, passed as a string. |
...points | string | Optional | Cumulative points threshold, passed as a string. |
...tracker | array | Optional | Tracker conditions. Max one entry. |
....trackerName | string | Optional | Tracker display name. |
....value | string | Conditional | Threshold value, passed as a string. Required for a tracker entry. |
....trackerId | integer | Conditional | Engine tracker instance ID. Required for a tracker entry. |
....trackerCondition | integer | Conditional | Engine tracker-definition ID. Required for a tracker entry. |
Note: The request body is validated in strict mode. Any unknown field is rejected with HTTP 400. The following read-only or program-level fields must not be sent on create or update requests:
downgrade,eligibilityCriteriaType,isActive,reminders,downgradeConfirmation,renewalConfirmation,retainPoints,dailyDowngradeEnabled,isDowngradeOnReturnEnabled,isDowngradeOnPartnerProgramExpiryEnabled,schedule,nudges,notificationConfig, andvalidity.endDate. Sentinel values of-1(numeric or string) inprogramId,periodValue, orthresholdare also rejected.
Example response
{
"data": {
"tierUniqueId": "ut-973-010",
"objectId": "6a2aab5cb1f2f8016a6598bb",
"name": "Super Platinum",
"description": "Premium tier for top spenders",
"color": "#E5E4E2",
"serialNumber": 10,
"eligibility": {
"kpiType": "CURRENT_POINTS",
"threshold": 100000,
"upgradeType": "LAZY"
},
"meta": {
"createdBy": "75237721",
"createdAt": "2026-06-11T12:34:36Z",
"updatedBy": "75237721",
"updatedAt": "2026-06-11T12:34:36Z"
},
"status": "DRAFT",
"origin": "MONGO_ONLY",
"renewal": {
"periodType": "SLAB_UPGRADE",
"periodValue": "12",
"unit": "NUM_MONTHS",
"criteriaType": "Same as eligibility"
}
},
"errors": null,
"warnings": null
}Response parameters
| Field | Type | Description |
|---|---|---|
data | object | Object containing the created tier. |
.tierUniqueId | string | Unique ID assigned to the tier (format ut-<programId>-<sequence>). Use it with Get Tier. |
.objectId | string | Unique ID of this tier record. Use it with Update Tier, Delete Tier, and the approval endpoints. |
.name | string | Tier name. |
.description | string | Tier description. |
.color | string | Display color in hex format. |
.serialNumber | integer | Tier position in the program's tier ladder. |
.eligibility | object | Object containing the conditions a customer must meet to enter this tier, as submitted. |
..kpiType | enum | KPI the threshold is measured against. Possible values: CURRENT_POINTS, CUMULATIVE_POINTS, CUMULATIVE_PURCHASES, TRACKER_VALUE_BASED. |
..threshold | number | KPI value at which a customer upgrades into this tier. |
..upgradeType | enum | When tier upgrades are evaluated. Possible values: EAGER, DYNAMIC, LAZY. |
.meta | object | Object containing details of who created and last updated the tier, and when. |
..createdBy | string | User or till ID of the person who created the tier. |
..createdAt | timestamp | Date and time when the tier was created, in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ), returned in the server time zone. |
..updatedBy | string | User or till ID of the person who last updated the tier. |
..updatedAt | timestamp | Date and time when the tier was last updated, in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ), returned in the server time zone. |
.status | string | Current stage of the tier lifecycle. Always DRAFT on creation. Possible values: DRAFT, PENDING_APPROVAL, REJECTED, ACTIVE, DELETED, SNAPSHOT, PUBLISH_FAILED, LIVE. |
.origin | string | Indicates which version of the tier data this entry represents. Always MONGO_ONLY for a new draft. Possible values: BOTH (published tier that also has a draft), MONGO_ONLY (draft not yet published), LEGACY_SQL_ONLY (tier created outside this API). |
.renewal | object | Object containing the tier's validity period and renewal settings, derived from validity. Read-only. |
..periodType | enum | Defines when the tier validity period starts. Possible values: FIXED (starts on a fixed date), SLAB_UPGRADE (starts when the customer enters the tier), SLAB_UPGRADE_CYCLIC (restarts each cycle after the upgrade), FIXED_CUSTOMER_REGISTRATION (starts on the customer's registration date). |
..periodValue | string | Tier duration in months, returned as a string. |
..unit | string | Unit of periodValue. Always NUM_MONTHS. |
..criteriaType | string | Renewal criteria type. Always Same as eligibility. |
errors | array | Error list. null on success. |
warnings | array | Warning list. null on success. |
Error & warning codes
| Code | Error number | Type | Description |
|---|---|---|---|
TIER.PROGRAM_ID_REQUIRED | 9003 | Error | programId is missing. HTTP 400. |
TIER.NAME_REQUIRED | 9001 | Error | name is missing or blank. HTTP 400. |
TIER.NAME_TOO_LONG | 9002 | Error | name exceeds 50 characters. HTTP 400. |
TIER.INVALID_KPI_TYPE | 9004 | Error | eligibility.kpiType or a condition type is not a supported value. HTTP 400. |
TIER.THRESHOLD_MUST_BE_POSITIVE | 9005 | Error | eligibility.threshold is negative. HTTP 400. |
TIER.INVALID_COLOR_CODE | 9006 | Error | color is not in #RRGGBB hex format. HTTP 400. |
TIER.DESCRIPTION_TOO_LONG | 9008 | Error | description exceeds 500 characters. HTTP 400. |
TIER.INVALID_UPGRADE_TYPE | 9009 | Error | eligibility.upgradeType is not a supported value. HTTP 400. |
TIER.INVALID_RENEWAL_CRITERIA | 9010 | Error | validity.periodType is not a supported value. HTTP 400. |
TIER.CLASS_A_PROGRAM_LEVEL_FIELD | 9011 | Error | A program-level field was sent on a per-tier write. HTTP 400. |
TIER.CLASS_B_SCHEDULE_FIELD | 9012 | Error | A schedule-shaped field was sent on a per-tier write. HTTP 400. |
TIER.ELIGIBILITY_CRITERIA_TYPE | 9013 | Error | eligibilityCriteriaType is read-only and was sent on a write request. HTTP 400. |
TIER.START_DATE_ON_SLAB_UPGRADE | 9014 | Error | validity.startDate was sent with a SLAB_UPGRADE family periodType. HTTP 400. |
TIER.SENTINEL_STRING_MINUS_ONE | 9015 | Error | A numeric field contains the string sentinel "-1". HTTP 400. |
TIER.SENTINEL_NUMERIC_MINUS_ONE | 9016 | Error | A numeric field contains the sentinel value -1. HTTP 400. |
TIER.RENEWAL_CRITERIA_TYPE_DRIFT | 9017 | Error | renewal.criteriaType is not exactly Same as eligibility. HTTP 400. |
TIER.FIXED_FAMILY_MISSING_PERIOD_VALUE | 9018 | Error | validity.periodValue is missing or not positive for a FIXED period type. HTTP 400. |
TIER.RENEWAL_DOWNGRADE_TO_INVALID | 9019 | Error | renewal.downgradeTo is not one of SINGLE, THRESHOLD, LOWEST. HTTP 400. |
TIER.RENEWAL_MULTI_TRACKER | 9020 | Error | renewal.conditions.tracker has more than one entry. HTTP 400. |
TIER.RENEWAL_EXPRESSION_INVALID | 9021 | Error | The renewal or eligibility expression is not a valid DNF expression. HTTP 400. |
TIER.VALIDITY_RENEWAL_WINDOW_TYPE | 9022 | Error | validity.renewalWindowType is not a supported value. HTTP 400. |
TIER.VALIDITY_COMPUTATION_WINDOW_ORPHAN | 9023 | Error | A computation window offset was sent without renewalWindowType. HTTP 400. |
TIER.VALIDITY_NUMERIC_NEGATIVE | 9024 | Error | A validity numeric field is negative. HTTP 400. |
TIER.UPGRADE_VALUE_OUT_OF_RANGE | 9028 | Error | eligibility.threshold exceeds 2,147,483,647. HTTP 400. |
TIER.TRACKER_ID_REQUIRED | 9029 | Error | A TRACKER condition is missing trackerId or trackerCondition. HTTP 400. |
TIER.PERIOD_VALUE_OVERFLOW | 9030 | Error | A numeric value exceeds 25 digits. HTTP 400. |
TIER.CUSTOM_PERIOD_DELTA_TOO_LARGE | 9033 | Error | For CUSTOM_PERIOD, the start-minus-end offset difference exceeds 35. HTTP 400. |
TIER.FIXED_DATE_OFFSET_OUT_OF_RANGE | 9034 | Error | For FIXED_DATE_BASED, computationWindowStartValue is outside 1–36. HTTP 400. |
TIER.MIN_DURATION_MUST_BE_POSITIVE | 9035 | Error | validity.minimumDuration is negative. HTTP 400. |
TIER.PROGRAM_KPI_TYPE_MISMATCH | 9043 | Error | The eligibility condition type is not compatible with the program's KPI type. HTTP 400. |
TIER.THRESHOLD_NOT_MONOTONIC | 9044 | Error | The tier threshold is not greater than the previous tier's threshold. HTTP 400. |
TIER.INVALID_PERIOD_UNIT | 9047 | Error | validity.unit is not NUM_MONTHS. HTTP 400. |
TIER.END_DATE_FORBIDDEN_ON_WRITE | 9048 | Error | validity.endDate is read-only and was sent on a write request. HTTP 400. |
TIER.RENEWAL_WINDOW_REQUIRES_FIXED_PERIOD_TYPE | 9049 | Error | renewalWindowType was sent with a periodType other than FIXED. HTTP 400. |
TIER.LAST_CALENDAR_YEAR_FORBIDS_OFFSETS | 9050 | Error | Computation window offsets were sent with renewalWindowType of LAST_CALENDAR_YEAR. HTTP 400. |
TIER.PROGRAM_UPGRADE_MODE_MISMATCH | 9051 | Error | eligibility.upgradeType doesn't match the program's slab upgrade mode. HTTP 400. |
TIER.PROGRAM_DOWNGRADE_STRATEGY_NOT_CONFIGURED | 9052 | Error | The program has no SLAB_DOWNGRADE strategy. Configure Tier Advanced Settings first. HTTP 400. |
TIER.PROGRAM_UPGRADE_STRATEGY_NOT_CONFIGURED | 9053 | Error | The program has no SLAB_UPGRADE strategy. Configure Tier Advanced Settings first. HTTP 400. |
TIER.PROGRAM_TIER_CAP_EXCEEDED | 9054 | Error | The program already has 50 tiers. HTTP 400. |
TIER.DOWNGRADE_START_DATE_MUST_BE_FIRST | 9055 | Error | validity.startDate is not the first day of the month while downgrade is enabled. HTTP 400. |
TIER_NAME_TAKEN | — | Error | A live tier with the same name already exists in the program. HTTP 409. |
TIER_DRAFT_EXISTS | — | Error | The program already has an in-progress DRAFT tier. HTTP 409. |
TIER_PENDING_APPROVAL_EXISTS | — | Error | The program already has a tier pending approval. HTTP 409. |
Note: Conflict errors (HTTP 409) return the generic error number
999999with a descriptive message on the wire. The Code column shows the stable symbolic code for these cases.
400Validation error: see the error table in the doc page
409Conflict: name taken, or a DRAFT or pending tier already exists in the program
