Loyalty Groups API
The Loyalty Groups API allows you to manage loyalty group segmentation in the Nilo platform. Loyalty groups define tiers or segments of customers for targeted loyalty programs, controlling which challenges and point lists apply to different customer segments.
Understanding Loyalty Groups
Loyalty groups in Nilo segment your customer base for loyalty programs:
-
Group Structure
- Unique internal code for identification
- Name for display purposes
- Enabled/disabled status
- Optional maximum redeemable points per order
- Optional association with a point list
-
Usage
- Link loyalty challenges to specific groups
- Control point redemption limits per segment
- Associate point lists with customer tiers
Important Considerations
- Unique Codes: Each loyalty group requires a unique internal code
- Point Limits: Use
maxRedeemablePointsPerOrderto cap point redemption per purchase - Point Lists: Associate a point list to define earning rules for the group
- Challenges: Loyalty challenges can target specific groups via
loyaltyGroupInternalCodes
Batch Operations
Batch Upsert Loyalty Groups
/batch/grouper/loyalty/upsertThis endpoint allows you to create or update multiple loyalty groups at once. The operation is processed asynchronously.
Use this endpoint when you need to:
- Set up your loyalty tier structure (Gold, Silver, Bronze, etc.)
- Synchronize loyalty groups from your CRM or loyalty management system
- Update point redemption limits across multiple groups
- Associate point lists with loyalty groups in bulk
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| upsert | array | Yes | Array of loyalty group objects |
| upsert[].internalCode | string | Yes | Unique loyalty group code |
| upsert[].name | string | Yes | Loyalty group display name |
| upsert[].enabled | boolean | Yes | Whether the group is active |
| upsert[].maxRedeemablePointsPerOrder | integer | No | Maximum points redeemable per order (null for unlimited) |
| upsert[].pointListInternalCode | string | No | Point list to associate with this group |
Request Body Example
{
"upsert": [
{
"internalCode": "GROUP-GOLD",
"name": "Gold Members",
"enabled": true,
"maxRedeemablePointsPerOrder": 5000,
"pointListInternalCode": "POINTS-GOLD"
},
{
"internalCode": "GROUP-SILVER",
"name": "Silver Members",
"enabled": true,
"maxRedeemablePointsPerOrder": 2000,
"pointListInternalCode": "POINTS-SILVER"
},
{
"internalCode": "GROUP-BRONZE",
"name": "Bronze Members",
"enabled": true,
"maxRedeemablePointsPerOrder": 1000,
"pointListInternalCode": null
}
]
}
Response Codes
| Code | Description |
|---|---|
| 202 | Request accepted, processing initiated |
| 400 | Bad request - Invalid parameters |
| 403 | Forbidden - Insufficient permissions |
Response Example
{
"batchIds": ["550e8400-e29b-41d4-a716-446655440000"]
}
Example Usage
- Javascript
- Python
const headers = {
Authorization: "YOUR_AUTH_TOKEN",
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
};
const data = {
upsert: [
{
internalCode: "GROUP-GOLD",
name: "Gold Members",
enabled: true,
maxRedeemablePointsPerOrder: 5000,
pointListInternalCode: "POINTS-GOLD",
},
{
internalCode: "GROUP-SILVER",
name: "Silver Members",
enabled: true,
maxRedeemablePointsPerOrder: 2000,
pointListInternalCode: "POINTS-SILVER",
},
{
internalCode: "GROUP-BRONZE",
name: "Bronze Members",
enabled: true,
maxRedeemablePointsPerOrder: 1000,
pointListInternalCode: null,
},
],
};
fetch(
"https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/batch/grouper/loyalty/upsert",
{
method: "POST",
headers: headers,
body: JSON.stringify(data),
}
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));
import requests
url = "https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/batch/grouper/loyalty/upsert"
headers = {
'Authorization': 'YOUR_AUTH_TOKEN',
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
}
data = {
"upsert": [
{
"internalCode": "GROUP-GOLD",
"name": "Gold Members",
"enabled": True,
"maxRedeemablePointsPerOrder": 5000,
"pointListInternalCode": "POINTS-GOLD"
},
{
"internalCode": "GROUP-SILVER",
"name": "Silver Members",
"enabled": True,
"maxRedeemablePointsPerOrder": 2000,
"pointListInternalCode": "POINTS-SILVER"
},
{
"internalCode": "GROUP-BRONZE",
"name": "Bronze Members",
"enabled": True,
"maxRedeemablePointsPerOrder": 1000,
"pointListInternalCode": None
}
]
}
response = requests.post(url, headers=headers, json=data)
print(response.text)
Error Codes
When an operation fails, the API returns a structured error response:
{
"code": 404,
"message": "LOYALTY_GROUP_NOT_FOUND",
"object": {
"statusCode": 404,
"code": "LOYALTY_GROUP_NOT_FOUND",
"message": "Loyalty group not found",
"entity": "loyaltyGroup",
"entityCode": "LG-001",
"timestamp": "2026-05-18T15:16:47.000Z"
}
}
The object field provides additional context about the error:
| Field | Description |
|---|---|
statusCode | HTTP status code |
code | Error code (same as top-level message) |
message | Human-readable error description |
entity | Entity type that caused the error |
entityCode | The internalCode of the entity involved |
timestamp | When the error occurred (ISO 8601) |
404 — Not Found
| Error Code | Description |
|---|---|
LOYALTY_GROUP_NOT_FOUND | The loyalty group does not exist |
POINT_LIST_NOT_FOUND | The point list specified does not exist |
STORE_NOT_FOUND | The store specified does not exist |
400 — Bad Request
| Error Code | Description |
|---|---|
MAX_REDEEMABLE_POINTS_PER_ORDER_IS_DECIMAL | The maximum redeemable points per order must be an integer |
409 — Conflict
| Error Code | Description |
|---|---|
NAME_ALREADY_EXIST | A loyalty group with the same name already exists |
INTERNAL_CODE_ALREADY_EXIST | A loyalty group with the same internal code already exists |
STORE_ALREADY_IN_LOYALTY_GROUP | The store is already assigned to this loyalty group |
STORE_NOT_IN_LOYALTY_GROUP | The store is not in this loyalty group (when trying to remove) |
LOYALTY_GROUP_HAS_NO_POINT_LIST | Cannot add a store because the loyalty group has no point list assigned |
Security
Authentication
All endpoints require two types of authentication:
- API Key in header:
x-api-key - Authorization token in header:
Authorization
Required Permissions
- For loyalty group operations:
supplier/loyaltygroup.bulkwrite