Skip to main content

Loyalty Challenges API

The Loyalty Challenges API allows you to manage loyalty programs and challenges in the Nilo platform. Loyalty challenges reward customers with points when they purchase specific products and reach a required amount.

Understanding Loyalty Challenges​

Loyalty Challenges in Nilo are gamified promotions that reward customers:

  • Challenge Structure
    • Unique internal code for identification
    • Title and description for display
    • Points given as reward
    • Required purchase amount to achieve the challenge
    • Validity period (start and end dates)
    • List of products that qualify for the challenge

Important Considerations​

  1. Unique Codes: Each challenge requires a unique internal code (same as in your ERP)
  2. Points System: Define how many points customers earn when completing the challenge
  3. Required Amount: Set the minimum purchase amount needed to complete the challenge
  4. Product Scope: Specify which products count towards the challenge
  5. Date Validity: Challenges are only active within the start and end dates

Single Challenge Operations​

Get Loyalty Challenge Details​

GET/loyaltychallenge/{code}

Retrieve detailed information about a specific loyalty challenge.

Path Parameters​

ParameterTypeRequiredDescription
codestringYesInternal code of the loyalty challenge

Response Example​

{
"id": 1,
"title": "Summer Points Challenge",
"description": "Earn points on summer products",
"image": "https://example.com/challenge.jpg",
"internalCode": "CHALLENGE-001",
"pointsGiven": 100,
"requiredMoney": 500,
"enabled": true,
"startDate": "2025-06-01",
"endDate": "2025-08-31",
"products": [
{
"internalCode": "PROD-001"
},
{
"internalCode": "PROD-002"
}
]
}

Example Usage​

const headers = {
Authorization: "YOUR_AUTH_TOKEN",
"x-api-key": "YOUR_API_KEY",
};

fetch(
"https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/loyaltychallenge/CHALLENGE-001",
{
method: "GET",
headers: headers,
}
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));

List All Loyalty Challenges​

GET/loyaltychallenge

Retrieve a list of all loyalty challenges with pagination and filtering support.

Query Parameters​

ParameterTypeRequiredDescription
takenumberNoNumber of items per page (default: 50, max: 50)
pagestringNoPage number (default: 1)
cursorstringNoCursor for pagination. First call should pass 0, subsequent calls use the cursor from the previous response
enabledbooleanNoFilter by enabled status
fromstringNoStart date filter (YYYY-MM-DD)
tostringNoEnd date filter (YYYY-MM-DD)

Create or Update Loyalty Challenge​

PUT/loyaltychallenge

Create a new loyalty challenge or update an existing one.

Request Body Parameters​

ParameterTypeRequiredDescription
titlestringYesTitle of the challenge
internalCodestringYesUnique identifier for the challenge
descriptionstringNoDescription of the challenge
imagestringNoURL of the challenge image
pointsGivennumberYesPoints awarded when challenge is completed
requiredAmountnumberYesMinimum purchase amount to complete challenge
startstringYesStart date (YYYY-MM-DD)
endstringYesEnd date (YYYY-MM-DD)
enabledbooleanYesWhether the challenge is active
productsarrayYesArray of products that qualify for the challenge

Request Body Example​

{
"title": "Summer Points Challenge",
"internalCode": "CHALLENGE-001",
"description": "Earn 100 points when you spend $500 on summer products",
"image": "https://example.com/challenge.jpg",
"pointsGiven": 100,
"requiredAmount": 500,
"start": "2025-06-01",
"end": "2025-08-31",
"enabled": true,
"products": [
{
"internalCode": "PROD-001"
},
{
"internalCode": "PROD-002"
}
]
}

Example Usage​

const headers = {
Authorization: "YOUR_AUTH_TOKEN",
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
};

const data = {
title: "Summer Points Challenge",
internalCode: "CHALLENGE-001",
description: "Earn 100 points when you spend $500 on summer products",
image: "https://example.com/challenge.jpg",
pointsGiven: 100,
requiredAmount: 500,
start: "2025-06-01",
end: "2025-08-31",
enabled: true,
products: [
{ internalCode: "PROD-001" },
{ internalCode: "PROD-002" },
],
};

fetch(
"https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/loyaltychallenge",
{
method: "PUT",
headers: headers,
body: JSON.stringify(data),
}
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));

Change Loyalty Challenge Status​

PUT/loyaltychallenge/{code}/status

Enable or disable a specific loyalty challenge.

Path Parameters​

ParameterTypeRequiredDescription
codestringYesInternal code of the loyalty challenge

Request Body Parameters​

ParameterTypeRequiredDescription
enabledbooleanYesNew status of the challenge

Request Body Example​

{
"enabled": true
}

Example Usage​

const headers = {
Authorization: "YOUR_AUTH_TOKEN",
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
};

const data = {
enabled: false,
};

fetch(
"https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/loyaltychallenge/CHALLENGE-001/status",
{
method: "PUT",
headers: headers,
body: JSON.stringify(data),
}
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));

Batch Operations​

Batch Upsert Loyalty Challenges​

POST/batch/loyalty-challenge

This endpoint allows you to create or update multiple loyalty challenges at once. The operation is processed asynchronously.

Use this endpoint when you need to:

  • Set up multiple loyalty challenges simultaneously
  • Synchronize challenges from your ERP or loyalty management system
  • Bulk update challenge parameters (points, dates, products)

Request Body Parameters​

ParameterTypeRequiredDescription
upsertarrayYesArray of loyalty challenge objects
upsert[].titlestringYesChallenge display title
upsert[].descriptionstringNoChallenge description
upsert[].imagestringNoChallenge image URL
upsert[].internalCodestringYesUnique challenge code (same as in ERP)
upsert[].startstringYesStart date (format: YYYY-MM-DD)
upsert[].endstringYesEnd date (format: YYYY-MM-DD)
upsert[].pointsGivennumberYesPoints awarded when completing the challenge
upsert[].requiredAmountnumberYesMinimum purchase amount required to complete
upsert[].enabledbooleanYesWhether the challenge is active
upsert[].productsarrayYesProducts that qualify for the challenge
upsert[].loyaltyGroupInternalCodesarrayNoInternal codes of loyalty groups to associate

Product Object Parameters​

ParameterTypeRequiredDescription
internalCodestringYesProduct internal code
unitsnumberYesRequired units of this product

Request Body Example​

{
"upsert": [
{
"title": "Buy 10 Sodas Challenge",
"description": "Purchase 10 units of any soda to earn 500 points",
"internalCode": "CHALLENGE-001",
"start": "2025-12-01",
"end": "2025-12-31",
"pointsGiven": 500,
"requiredAmount": 10,
"enabled": true,
"products": [
{ "internalCode": "PROD-001", "units": 5 },
{ "internalCode": "PROD-002", "units": 5 }
],
"loyaltyGroupInternalCodes": ["GROUP-GOLD", "GROUP-SILVER"]
},
{
"title": "Snack Lover Challenge",
"internalCode": "CHALLENGE-002",
"start": "2025-12-01",
"end": "2026-01-31",
"pointsGiven": 200,
"requiredAmount": 5,
"enabled": true,
"products": [
{ "internalCode": "SNACK-001", "units": 5 }
]
}
]
}

Response Codes​

CodeDescription
202Request accepted, processing initiated
400Bad request - Invalid parameters
403Forbidden - Insufficient permissions

Response Example​

{
"code": 202,
"batchIds": {},
"message": "Operation in processing"
}

Example Usage​

const headers = {
Authorization: "YOUR_AUTH_TOKEN",
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
};

const data = {
upsert: [
{
title: "Buy 10 Sodas Challenge",
internalCode: "CHALLENGE-001",
start: "2025-12-01",
end: "2025-12-31",
pointsGiven: 500,
requiredAmount: 10,
enabled: true,
products: [
{ internalCode: "PROD-001", units: 5 },
{ internalCode: "PROD-002", units: 5 },
],
loyaltyGroupInternalCodes: ["GROUP-GOLD"],
},
],
};

fetch(
"https://tm0cs5kjs6.execute-api.us-east-1.amazonaws.com/dev/batch/loyalty-challenge",
{
method: "POST",
headers: headers,
body: JSON.stringify(data),
}
)
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));

Error Codes​

When an operation fails, the API returns a structured error response:

{
"code": 404,
"message": "LOYALTY_CHALLENGE_NOT_FOUND",
"object": {
"statusCode": 404,
"code": "LOYALTY_CHALLENGE_NOT_FOUND",
"message": "Loyalty challenge not found",
"entity": "loyaltyChallenge",
"entityCode": "LC-001",
"timestamp": "2026-05-18T15:16:47.000Z"
}
}

The object field provides additional context about the error:

FieldDescription
statusCodeHTTP status code
codeError code (same as top-level message)
messageHuman-readable error description
entityEntity type that caused the error
entityCodeThe internalCode of the entity involved
timestampWhen the error occurred (ISO 8601)

404 — Not Found​

Error CodeDescription
LOYALTY_CHALLENGE_NOT_FOUNDThe loyalty challenge does not exist
PRODUCT_CODE_NOT_FOUNDOne of the product codes in the challenge does not exist
LOYALTY_GROUP_NOT_FOUNDThe loyalty group to add/remove does not exist

400 — Bad Request​

Error CodeDescription
START_DATE_AFTER_END_DATEThe start date is after the end date
POINTS_GIVEN_IS_NEGATIVEThe points given value must be positive
POINTS_GIVEN_IS_DECIMALThe points given value must be an integer
REQUIRED_AMOUNT_IS_NOT_POSITIVEThe required amount must be greater than zero
DUPLICATE_PRODUCT_CODEThe same product code appears more than once in the request

409 — Conflict​

Error CodeDescription
INTERNAL_CODE_ALREADY_EXISTA challenge with the same internal code already exists
LOYALTY_GROUP_ALREADY_IN_LOYALTY_CHALLENGEThe loyalty group is already associated with this challenge
LOYALTY_GROUP_HAS_CONFLICTSThe loyalty group has conflicting assignments with other challenges
LOYALTY_GROUP_NOT_IN_LOYALTY_CHALLENGEThe loyalty group is not associated with this challenge (when trying to remove)

Security​

Authentication​

All endpoints require two types of authentication:

  • API Key in header: x-api-key
  • Authorization token in header: Authorization

Required Permissions​

  • For reading operations: supplier/loyaltychallenge.read
  • For writing operations: supplier/loyaltychallenge.write
  • For batch operations: supplier/loyaltychallenge.bulkwrite
Tana

Tana

Ask me anything about Nilo's API — endpoints, authentication, integration guides, or code examples.

Best practice: validate against the official documentation for the most up-to-date details.