### GET /shop
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves configuration and settings for the current shop.
```APIDOC
## GET /shop
### Description
Fetches shop-specific settings including currency, plan status, and branding preferences.
### Method
GET
### Endpoint
joyInstance.shop()
### Response
#### Success Response (200)
- **plan** (string) - Current subscription plan
- **currency** (string) - Shop currency code
- **disableWatermark** (boolean) - Whether the watermark is disabled
#### Response Example
{
"disableWatermark": true,
"plan": "free",
"currency": "VND"
}
```
--------------------------------
### Perform Authenticated GET Request via cURL
Source: https://devdocs.joy.so/joy-rest-api-v2/rest-api-v2
An example of how to authenticate and fetch customer data using the cURL command-line tool. It demonstrates the inclusion of required headers and content-type.
```bash
curl -X GET "https://dev-api.joy.so/rest_api/v2/customers" \
-H "X-Joy-Loyalty-App-Key: your_app_key" \
-H "X-Joy-Loyalty-Secret-Key: your_secret_key" \
-H "Content-Type: application/json"
```
--------------------------------
### cURL Authentication Example
Source: https://devdocs.joy.so/webhook-api/authentication
Demonstrates how to make an authenticated GET request to the Joy Loyalty API's webhooks endpoint using cURL. It includes the necessary authentication headers and content type.
```bash
curl -X GET "https://joy.avada.io/app/api/v1/webhooks" \
-H "X-Joy-Loyalty-App-Key: your_app_key" \
-H "X-Joy-Loyalty-Secret-Key: your_secret_key" \
-H "Content-Type: application/json"
```
--------------------------------
### Implement Joy Loyalty Webhook Server and API Client
Source: https://devdocs.joy.so/webhook-api/integration-examples
A complete implementation for handling Joy Loyalty webhooks with HMAC signature verification and managing API resources. Includes examples for both Express (Node.js) and Flask (Python) frameworks.
```javascript
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');
const app = express();
const joyApi = axios.create({
baseURL: 'https://joy.avada.io/app/api/v1',
headers: {
'X-Joy-Loyalty-App-Key': process.env.JOY_APP_KEY,
'X-Joy-Loyalty-Secret-Key': process.env.JOY_SECRET_KEY
}
});
function verifyWebhook(req, res, next) {
const hmac = req.get('X-Joy-Loyalty-Hmac-Sha256');
const calculatedHmac = crypto
.createHmac('sha256', process.env.JOY_SECRET_KEY)
.update(req.rawBody, 'utf8')
.digest('base64');
if (!crypto.timingSafeEqual(Buffer.from(calculatedHmac), Buffer.from(hmac))) {
return res.status(401).send('Invalid signature');
}
next();
}
app.use('/webhook', express.raw({type: 'application/json'}), (req, res, next) => {
req.rawBody = req.body;
req.body = JSON.parse(req.body);
next();
});
app.post('/webhook/points-earned', verifyWebhook, (req, res) => {
const {customer, oldPoint, newPoint} = req.body;
res.status(200).send('OK');
});
```
```python
import hmac, hashlib, base64, requests
from flask import Flask, request
class JoyWebhookClient:
def __init__(self, app_key, secret_key):
self.secret_key = secret_key
self.base_url = 'https://joy.avada.io/app/api/v1'
self.session = requests.Session()
self.session.headers.update({'X-Joy-Loyalty-App-Key': app_key, 'X-Joy-Loyalty-Secret-Key': secret_key})
def verify_webhook(self, raw_body, hmac_header):
calculated_hmac = base64.b64encode(
hmac.new(self.secret_key.encode('utf-8'), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(calculated_hmac, hmac_header)
def list_webhooks(self):
response = self.session.get(f'{self.base_url}/webhooks')
return response.json().get('webhooks', [])
```
--------------------------------
### GET /customer
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves information for the currently logged-in customer on the store.
```APIDOC
## GET /customer
### Description
Retrieves the customer profile information for the currently authenticated user.
### Method
GET
### Endpoint
joyInstance.customer()
### Response
#### Success Response (200)
- **id** (string) - Unique customer identifier
- **shopifyCustomerId** (number) - Shopify customer ID
- **email** (string) - Customer email address
- **point** (number) - Current loyalty point balance
#### Response Example
{
"id": "avsu0TQoHYd4Zq5TZ123",
"shopifyCustomerId": 123123123,
"name": "admin super",
"point": 100
}
```
--------------------------------
### GET /redeemPrograms
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves the list of active redemption programs available to customers.
```APIDOC
## GET /redeemPrograms
### Description
Fetches all configured redemption programs, including point requirements and reward types.
### Method
GET
### Endpoint
joyInstance.redeemPrograms()
### Response
#### Success Response (200)
- **programs** (array) - List of redemption program objects
#### Response Example
[
{
"id": "MuvzQblxTj4b7jsUUJzM",
"title": "Free product",
"spendPoint": 200
}
]
```
--------------------------------
### Get Earning Programs List
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves a list of available earning programs from the public API. This method is asynchronous and returns a Promise that resolves with the program data.
```javascript
joyInstance.earnPrograms().then(function(resp){
console.log(resp)
});
```
--------------------------------
### GET /translation
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves the translation dictionary for the store's loyalty program interface.
```APIDOC
## GET /translation
### Description
Returns a dictionary of key-value pairs used for localizing the loyalty program UI.
### Method
GET
### Endpoint
joyInstance.translation()
### Response
#### Success Response (200)
- **dictionary** (object) - Key-value pairs of translation strings
#### Response Example
{
"Earn": "Earn",
"Spend": "Spend",
"Back": "Back"
}
```
--------------------------------
### Webview Authentication for Joy Loyalty SDK (KoaJS Example)
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk
This JavaScript code provides a KoaJS example for rendering the Joy widget in a webview. It generates a customer hash secret using Node.js crypto and embeds the necessary shop and customer information into an HTML structure for the Joy SDK.
```javascript
const {
shopId, // App ID
shopifyCustomerId, // Shopify customer ID
email, // Email of the customer
secretKey // Secret key of Joy
} = ...
const prepareEmailCustomer = email?.toLowerCase() || '';
const hash = crypto
.createHmac('sha256', secretKey)
.update(`${shopifyCustomerId}-${prepareEmailCustomer}-${shopId}`)
.digest('hex');
try {
return (ctx.body = `
Joy Loyalty SDK - Mobile WebView
`);
```
--------------------------------
### GET /app/api/v1/widgets/points-calculator/product
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Calculates the number of points a customer will earn for purchasing a specific product variant.
```APIDOC
## GET /app/api/v1/widgets/points-calculator/product
### Description
Retrieves the loyalty points calculation for a specific product variant based on the customer's context.
### Method
GET
### Endpoint
https://joy.avada.io/app/api/v1/widgets/points-calculator/product
### Parameters
#### Query Parameters
- **domain** (string) - Required - The Shopify shop domain.
- **productId** (string) - Required - The ID of the product.
- **variantId** (string) - Required - The ID of the product variant.
- **q** (number) - Optional - Quantity of the item.
- **customerId** (string) - Optional - The ID of the current customer.
### Response
#### Success Response (200)
- **html** (string) - Pre-rendered HTML snippet for the widget.
- **points** (number) - Calculated point value.
- **pointCurrencyName** (object) - Singular and plural labels for the currency.
- **fromCache** (boolean) - Indicates if the result was served from cache.
### Response Example
{
"html": "Receive 699 points...",
"points": 699,
"pointCurrencyName": {
"singular": "point",
"plural": "points"
},
"fromCache": false
}
```
--------------------------------
### Get Customer Coupon List
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves a list of customer coupons that have been redeemed. This method supports pagination using 'before' and 'after' parameters and can filter for available coupons.
```javascript
joyInstance.rewardList({before: '', after: '', isAvailableCoupon: true}).then(function(resp){
console.log(resp)
});
```
--------------------------------
### GET /loyalty/config
Source: https://devdocs.joy.so/joy-rest-api-v2/tiers
Retrieves the current loyalty program configuration, including point earning tiers and rounding logic.
```APIDOC
## GET /loyalty/config
### Description
Retrieves the configuration settings for the loyalty points system.
### Method
GET
### Endpoint
/loyalty/config
### Parameters
None
### Request Example
GET /loyalty/config
### Response
#### Success Response (200)
- **earnPointsTiers** (array) - List of objects containing earnPoint (integer) and rateMoney (number).
- **roundingMethod** (string) - The method used for rounding points (round, floor, ceil).
- **skipEarnPointGuest** (boolean) - Whether guests are excluded from earning points.
#### Response Example
{
"earnPointsTiers": [{"earnPoint": 1, "rateMoney": 10.0}],
"roundingMethod": "floor",
"skipEarnPointGuest": true
}
```
--------------------------------
### GET /rewards
Source: https://devdocs.joy.so/joy-rest-api-v2/tiers
Retrieves the configuration details for loyalty rewards, including points, priority, and localization settings.
```APIDOC
## GET /rewards
### Description
Retrieves the current loyalty reward configuration and status metadata.
### Method
GET
### Endpoint
/rewards
### Parameters
#### Query Parameters
- **id** (string) - Optional - The unique identifier for the reward.
### Request Example
GET /rewards?id=123
### Response
#### Success Response (200)
- **bonusPoints** (string) - Bonus points awarded
- **priority** (integer) - Reward priority
- **showLoyaltyPage** (boolean) - Whether to show on loyalty page
- **translateTitle** (object) - Translated titles for different languages
- **expired** (boolean) - Whether reward has expired
- **createdAt** (string) - Reward creation timestamp
- **updatedAt** (string) - Last update timestamp
#### Response Example
{
"bonusPoints": "500",
"priority": 1,
"showLoyaltyPage": true,
"translateTitle": { "en": "Gold Reward" },
"expired": false,
"createdAt": "2023-10-01T12:00:00Z",
"updatedAt": "2023-10-01T12:00:00Z"
}
```
--------------------------------
### Set up local webhook testing environment with ngrok
Source: https://devdocs.joy.so/webhook-api/troubleshooting
Instructions for installing ngrok and exposing a local development server to the internet for webhook testing.
```bash
# Install ngrok
npm install -g ngrok
# Start your local server
node webhook-server.js
# Create secure tunnel
ngrok http 3000
```
--------------------------------
### Initialize Joy API Node.js SDK
Source: https://devdocs.joy.so/joy-rest-api-v2/rest-api-v2
Shows how to initialize the official Joy API client and fetch shop information. Requires app and secret keys for authentication.
```javascript
import JoyApi from 'joy-api-node';
const joy = new JoyApi({
appKey: 'your-app-key',
secretKey: 'your-secret-key',
baseUrl: 'https://dev-api.joy.so',
timeout: 30000,
maxRetries: 3
});
// Get shop information
const shop = await joy.shop.whoami();
console.log(shop.data);
```
--------------------------------
### Initialize Announcement Logic
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/js-sdk-tutorial/how-to-make-a-coupon-reminder-using-joy-sdk
Handles the conditional rendering of the announcement bar based on the environment (editor vs. live) and user authentication status. It includes event listeners for Shopify section updates and session-based dismissal tracking.
```javascript
window.addEventListener('joy:ready', async () => {
if (IN_EDITOR) return;
if (!IS_CUSTOMER) return;
try {
if (document.getElementById('joy-announce-wrap')) return;
if (sessionStorage.getItem('joy_announcement_dismissed') === '1') return;
const ji = window.joyInstance || window.joy;
if (!ji) return;
const appliedCodes = await getAppliedDiscountCodes();
const resp = await ji.rewardList({ isAvailableCoupon: true });
const rewards = Array.isArray(resp?.data) ? resp.data : [];
const unused = rewards.filter(r => r?.couponCode && !r?.isUsedCode);
if (!unused.length) return;
const latest = unused[0];
const { wrap, bar } = createBar(latest.couponCode, latest.eventRule, latest.programDescription, TEMPLATE_MSG, BUTTON_TEXT);
document.body.appendChild(wrap);
const restorePad = addBottomPaddingWhileVisible();
bar.querySelector('.joy-dismiss')?.addEventListener('click', () => {
sessionStorage.setItem('joy_announcement_dismissed','1');
wrap.remove();
restorePad();
});
} catch(e) { console.error(e); }
});
```
--------------------------------
### Navigate Paginated Data with Cursors
Source: https://devdocs.joy.so/joy-rest-api-v2/rest-api-v2
Demonstrates how to navigate through large datasets using cursor-based pagination. It shows how to request the first page and subsequent pages using the 'before' and 'after' parameters.
```bash
# First page
curl "https://dev-api.joy.so/rest_api/v2/customers?limit=20&hasCount=true"
# Next page (using last item's ID from previous response)
curl "https://dev-api.joy.so/rest_api/v2/customers?after=abc123&limit=20"
# Previous page (using first item's ID)
curl "https://dev-api.joy.so/rest_api/v2/customers?before=abc123&limit=20"
```
--------------------------------
### Verify and Handle Webhooks
Source: https://devdocs.joy.so/webhook-api/integration-examples
Demonstrates how to verify incoming webhook requests using HMAC-SHA256 signatures and process event payloads. This implementation ensures data integrity before executing business logic.
```python
webhook_client = JoyWebhookClient(os.getenv('JOY_APP_KEY'), os.getenv('JOY_SECRET_KEY'))
@app.route('/webhook/points-earned', methods=['POST'])
def handle_points_earned():
hmac_header = request.headers.get('X-Joy-Loyalty-Hmac-Sha256')
if not webhook_client.verify_webhook(request.data, hmac_header):
return 'Invalid signature', 401
payload = request.get_json()
# Process payload logic here
return 'OK', 200
```
```php
$rawBody = file_get_contents('php://input');
$hmacHeader = $_SERVER['HTTP_X_JOY_LOYALTY_HMAC_SHA256'] ?? '';
if (!$webhookClient->verifyWebhook($rawBody, $hmacHeader)) {
http_response_code(401);
exit('Invalid signature');
}
$payload = json_decode($rawBody, true);
// Process payload logic here
echo 'OK';
```
--------------------------------
### Manage Webhooks via API
Source: https://devdocs.joy.so/webhook-api/integration-examples
Provides methods to create and list webhooks using the Joy Loyalty API. Requires valid App and Secret keys for authentication.
```php
public function createWebhook($topic, $url) {
$data = json_encode(['topic' => $topic, 'url' => $url]);
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => [
'Content-Type: application/json',
'X-Joy-Loyalty-App-Key: ' . $this->appKey,
'X-Joy-Loyalty-Secret-Key: ' . $this->secretKey
],
'content' => $data
]
]);
return json_decode(file_get_contents($this->baseUrl . '/webhooks', false, $context), true);
}
```
--------------------------------
### GET /rest_api/v2/programs/redemption
Source: https://devdocs.joy.so/joy-rest-api-v2/programs
Retrieves a list of all point spending and redemption programs available for the shop.
```APIDOC
## GET /rest_api/v2/programs/redemption
### Description
Retrieve all point spending/redemption programs configured for the shop. This endpoint supports filtering by customer ID and event type.
### Method
GET
### Endpoint
https://api.joy.so/rest_api/v2/programs/redemption
### Parameters
#### Header Parameters
- **X-Joy-Loyalty-App-Key** (string) - Required - App ID of your shop retrieved from the Settings page
- **X-Joy-Loyalty-Secret-Key** (string) - Required - Secret Key of your shop retrieved from the Settings page
#### Query Parameters
- **shopifyCustomerId** (string) - Optional - Shopify customer ID for program limitations
- **event** (string) - Optional - Filter by program event type (amount_discount, percentage_discount, free_shipping, free_gift)
### Request Example
GET /rest_api/v2/programs/redemption?event=amount_discount
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful
- **data** (array) - List of redemption programs
- **meta** (object) - Metadata including the count of items returned
#### Response Example
{
"success": true,
"data": [
{
"id": "prog_123",
"title": "10% Off",
"type": "spending",
"event": "percentage_discount"
}
],
"meta": {
"count": 1
}
}
```
--------------------------------
### GET /rest_api/v2/rewards/{rewardId}
Source: https://devdocs.joy.so/joy-rest-api-v2/rewards-1
Retrieves the details of a specific reward by its unique identifier. Requires authentication via shop-specific headers.
```APIDOC
## GET /rest_api/v2/rewards/{rewardId}
### Description
Retrieve detailed information about a specific reward using its unique ID. This endpoint returns the reward status, associated program details, and customer information.
### Method
GET
### Endpoint
/rest_api/v2/rewards/{rewardId}
### Parameters
#### Path Parameters
- **rewardId** (string) - Required - The unique identifier of the reward.
#### Headers
- **X-Joy-Loyalty-App-Key** (string) - Required - App ID of your shop retrieved from the Settings page.
- **X-Joy-Loyalty-Secret-Key** (string) - Required - Secret Key of your shop retrieved from the Settings page.
### Request Example
GET /rest_api/v2/rewards/reward_12345
Headers: {
"X-Joy-Loyalty-App-Key": "your_app_key",
"X-Joy-Loyalty-Secret-Key": "your_secret_key"
}
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful.
- **data** (object) - The reward object containing id, customerId, email, couponCode, and status.
- **message** (string) - Status message.
- **timestamp** (string) - ISO 8601 timestamp of the response.
#### Response Example
{
"success": true,
"data": {
"id": "reward_12345",
"email": "customer@example.com",
"couponCode": "SAVE20",
"discountStatus": "active",
"createdAt": "2023-10-01T10:00:00Z"
},
"message": "Success",
"timestamp": "2023-10-27T12:00:00Z"
}
```
--------------------------------
### Listen for Joy SDK Ready Event
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk
This JavaScript code demonstrates how to listen for the 'joy:ready' event, which fires once the Joy SDK has finished loading. This is useful for executing code that depends on the SDK being fully initialized.
```javascript
window.addEventListener('joy:ready', () => {
});
```
--------------------------------
### GET /rest_api/v2/rewards
Source: https://devdocs.joy.so/joy-rest-api-v2/rewards-1
Retrieve a list of customer rewards. You must provide either `customerId` or `shopifyCustomerId`. Supports filtering by status, type, creation date, and pagination.
```APIDOC
## GET /rest_api/v2/rewards
### Description
Retrieve customer rewards with optional filtering and pagination. Customer Identifier Required: Must provide either `customerId` or `shopifyCustomerId` parameter.
### Method
GET
### Endpoint
/rest_api/v2/rewards
### Parameters
#### Query Parameters
- **X-Joy-Loyalty-App-Key** (string) - Required - App ID of your shop which retrieved from the Settings page
- **X-Joy-Loyalty-Secret-Key** (string) - Required - Secret Key of your shop which retrieved from the Settings page
- **customerId** (string) - Required - Joy internal customer ID
- **shopifyCustomerId** (string) - Required - Shopify customer ID
- **status** (string) - Optional - Filter by reward status (active, used, expired)
- **typeReward** (string) - Optional - Filter by reward type
- **before** (string) - Optional - Cursor for pagination (before) - Firestore document ID of reward to paginate before
- **after** (string) - Optional - Cursor for pagination (after) - Firestore document ID of reward to paginate after
- **limit** (integer) - Optional - Number of rewards per page (default: 10, min: 1, max: 1000)
- **created_at_min** (string) - Optional - Filter rewards created after this date (ISO 8601 format)
- **created_at_max** (string) - Optional - Filter rewards created before this date (ISO 8601 format)
- **order** (string) - Optional - Sort order for results (createdAt_desc, createdAt_asc, updatedAt_desc, updatedAt_asc, default: createdAt_desc)
- **hasCount** (boolean) - Optional - Include total count in response (may increase response time, default: false)
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful.
- **data** (array) - An array of reward objects.
- **id** (string) - Reward ID
- **customerId** (string) - Internal customer ID
- **email** (string) - Customer email address
- **couponCode** (string) - Generated coupon/discount code
- **programTitle** (string) - Program title
- **shopifyCustomerId** (integer) - Shopify customer ID
- **programDescription** (string) - Program description
- **orderReqAmount** (string) - Minimum order amount required
- **expiredAt** (string) - Reward expiration date (nullable)
- **discountStatus** (string) - Status of the discount
- **meta** (object) - Pagination metadata.
- **pagination** (object) - Pagination details.
- **hasNext** (boolean) - True if more results exist after current page.
- **hasPre** (boolean) - True if results exist before current page.
- **total** (integer) - Total count of all matching results (when available).
- **totalPage** (integer) - Total number of pages calculated as ceil(total/limit) (when available).
#### Error Response (404)
- **success** (boolean) - Indicates if the request was successful.
- **data** (object) - Empty object.
- **message** (string) - Error message (e.g., "Customer not found").
- **timestamp** (string) - Timestamp of the error.
### Request Example
```json
{
"headers": {
"X-Joy-Loyalty-App-Key": "YOUR_APP_KEY",
"X-Joy-Loyalty-Secret-Key": "YOUR_SECRET_KEY"
},
"query": {
"customerId": "cust_12345",
"limit": 20,
"status": "active"
}
}
```
### Response Example (200 OK)
```json
{
"success": true,
"data": [
{
"id": "rew_abcde",
"customerId": "cust_12345",
"email": "customer@example.com",
"couponCode": "SUMMER20",
"programTitle": "Summer Sale Discount",
"shopifyCustomerId": 123456789,
"programDescription": "Get 20% off on your next order.",
"orderReqAmount": "50.00",
"expiredAt": "2024-12-31T23:59:59Z",
"discountStatus": "active"
}
],
"meta": {
"pagination": {
"hasNext": true,
"hasPre": false,
"total": 150,
"totalPage": 8
}
}
}
```
### Response Example (404 Not Found)
```json
{
"success": false,
"data": {},
"message": "Customer not found",
"timestamp": "2023-10-27T10:00:00Z"
}
```
```
--------------------------------
### Implement Asynchronous Webhook Processing (JavaScript)
Source: https://devdocs.joy.so/webhook-api/best-practices
This example shows how to handle long-running webhook processes by responding immediately and queuing the task for background processing. This improves responsiveness and avoids timeouts.
```javascript
app.post('/webhook', async (req, res) => {
// Respond immediately
res.status(200).send('OK');
// Queue for background processing
await addToQueue('webhook-processing', req.body);
});
```
--------------------------------
### GET /rest_api/v2/programs/{programId}
Source: https://devdocs.joy.so/joy-rest-api-v2/programs
Retrieve the details of a specific loyalty program by its unique identifier. This endpoint supports optional filtering based on a Shopify customer ID.
```APIDOC
## GET /rest_api/v2/programs/{programId}
### Description
Retrieve a specific loyalty program by its ID. This returns the full configuration of the program, including earning or spending rules.
### Method
GET
### Endpoint
/rest_api/v2/programs/{programId}
### Parameters
#### Path Parameters
- **programId** (string) - Required - The unique identifier of the program.
#### Query Parameters
- **shopifyCustomerId** (string) - Optional - Shopify customer ID used to check program limitations for a specific user.
### Request Example
GET https://api.joy.so/rest_api/v2/programs/prog_12345
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful.
- **data** (object) - The program object containing configuration details.
- **message** (string) - Status message.
- **timestamp** (string) - ISO 8601 timestamp of the response.
#### Response Example
{
"success": true,
"data": {
"id": "prog_12345",
"title": "Summer Sale Earning",
"type": "earning",
"status": true
},
"message": "Success",
"timestamp": "2023-10-27T10:00:00Z"
}
```
--------------------------------
### Theme Editor Preview Logic (JavaScript)
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/js-sdk-tutorial/how-to-make-a-coupon-reminder-using-joy-sdk
Handles the rendering of the announcement bar within the Shopify theme editor preview. It listens for section load and select events to re-render the preview, ensuring dynamic updates. Dependencies include the `mountBar` function and a global `inEditor` flag.
```javascript
(function editorPreview() {
try {
if (!inEditor) return;
const renderPreview = () => {
try {
document.getElementById('joy-announce-wrap')?.remove();
mountBar('JOY-PREVIEW10', 'reward', '10% off', { respectDismiss: false });
} catch (e) { console.log('renderPreview error', e); }
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', renderPreview);
} else {
renderPreview();
}
document.addEventListener('shopify:section:load', renderPreview);
document.addEventListener('shopify:section:select', renderPreview);
} catch (e) {
console.log('editorPreview error', e);
}
})();
```
--------------------------------
### Retrieve Shop Configuration via Joy API
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Retrieves the store's current configuration settings from the Joy API. Returns a Promise resolving to an object containing plan details, currency settings, and watermark preferences.
```javascript
joyInstance.shop().then(function(resp){
console.log(resp)
});
```
--------------------------------
### GET /rest_api/v2/programs/earning
Source: https://devdocs.joy.so/joy-rest-api-v2/programs
Retrieve all earning programs for the authenticated shop. This endpoint allows you to fetch a list of all active and inactive earning programs configured for your loyalty system.
```APIDOC
## GET /rest_api/v2/programs/earning
### Description
Retrieve all earning programs for the authenticated shop.
### Method
GET
### Endpoint
/rest_api/v2/programs/earning
### Parameters
#### Header Parameters
- **X-Joy-Loyalty-App-Key** (string) - Required - App ID of your shop which retrieved from the Settings page
- **X-Joy-Loyalty-Secret-Key** (string) - Required - Secret Key of your shop which retrieved from the Settings page
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful.
- **data** (array) - A list of earning program objects.
- **id** (string) - The unique identifier for the program.
- **title** (string) - The name of the earning program.
- **type** (string) - The type of program (e.g., "earning").
- **status** (boolean) - Indicates if the program is currently active.
- **createdAt** (string) - The timestamp when the program was created.
- **updatedAt** (string) - The timestamp when the program was last updated.
- **earnBy** (string) - The method by which points are earned (e.g., "price", "order").
- **rateMoney** (number) - The monetary value associated with earning points.
- **earnPoint** (integer) - The number of points earned.
- **startDate** (string) - The start date for the program.
- **endDate** (string) - The end date for the program.
#### Error Response (403)
- **success** (boolean) - Indicates if the request was successful.
- **message** (string) - Error message describing the issue (e.g., "Plan upgrade required").
#### Error Response (500)
- **success** (boolean) - Indicates if the request was successful.
- **message** (string) - Error message describing the internal server error.
### Response Example
```json
{
"success": true,
"data": [
{
"id": "prog_12345",
"title": "10% Back on Orders",
"type": "earning",
"status": true,
"createdAt": "2023-10-27T10:00:00Z",
"updatedAt": "2023-10-27T10:00:00Z",
"earnBy": "order",
"rateMoney": 0.10,
"earnPoint": 100,
"startDate": "2023-10-27T00:00:00Z",
"endDate": "2023-12-31T23:59:59Z"
}
],
"meta": {
"count": 1
}
}
```
```
--------------------------------
### Get Customer Activity History
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Fetches a list of customer activity history, supporting pagination via 'before' and 'after' parameters. The response includes activity data and pagination information.
```javascript
joyInstance.customerHistory({before: '', after: ''}).then(function(resp){
console.log(resp)
});
```
--------------------------------
### Live Joy Announcement Logic (JavaScript)
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/js-sdk-tutorial/how-to-make-a-coupon-reminder-using-joy-sdk
Manages the dynamic display of available coupon rewards on the live website. It fetches available rewards, checks against applied codes, and mounts the announcement bar if a new, unused coupon is found. It also includes logic to auto-hide the bar if the code is applied later. Dependencies include `getAppliedDiscountCodes`, `joyInstance` (or `joy`), and `mountBar`.
```javascript
window.addEventListener('joy:ready', async () => {
if (inEditor) return; // preview handles editor
try {
const ji = window.joyInstance || window.joy;
if (!ji) return;
if (document.getElementById('joy-announce-wrap')) return;
if (sessionStorage.getItem('joy_announcement_dismissed') === '1') return;
const appliedCodes = await getAppliedDiscountCodes();
let resp;
try {
resp = await ji.rewardList({ isAvailableCoupon: true });
} catch (e) {
console.log('rewardList error', e);
return;
}
const rewards = Array.isArray(resp?.data) ? resp.data : [];
const unused = rewards
.filter(r => r && r.couponCode && !r.isUsedCode)
.sort((a, b) => {
try { return new Date(b.createdAt) - new Date(a.createdAt); }
catch (_) { return 0; }
});
if (!unused.length) return;
const latest = unused[0];
const code = String(latest?.couponCode || '');
const label = String(latest?.eventRule || 'reward').replace(/_/g, ' ');
const benefit= latest?.programDescription || 'your coupon';
if (!code) return;
if (appliedCodes.includes(code.toUpperCase())) return;
const mounted = mountBar(code, label, benefit, { respectDismiss: true });
if (!mounted) return;
const maybeHide = async () => {
try {
const nowCodes = await getAppliedDiscountCodes();
if (nowCodes.includes(code.toUpperCase())) {
try { sessionStorage.setItem('joy_announcement_dismissed', '1'); } catch (_) {}
mounted.cleanup();
}
} catch (e) {
console.log('maybeHide error', e);
}
};
try {
mounted.bar.querySelector('.joy-cta')?.addEventListener('click', () => {
try { setTimeout(maybeHide, 1200); } catch (_) {}
});
} catch (e) { console.log('cta binding error', e); }
let checks = 0;
const iv = setInterval(async () => {
try {
checks++;
await maybeHide();
if (checks > 10 || !document.getElementById('joy-announce-wrap')) clearInterval(iv);
} catch (e) {
clearInterval(iv);
console.log('interval error', e);
}
}, 1000);
} catch (e) {
console.log('joy:ready handler error', e);
}
});
```
--------------------------------
### Get Shop Information (OpenAPI)
Source: https://devdocs.joy.so/joy-rest-api-v2/shop
Retrieves safe shop information for the authenticated shop. This OpenAPI definition specifies the endpoint, parameters, and response structure for the 'whoami' GET request.
```json
{
"openapi": "3.0.0",
"info": {
"title": "Joy Loyalty Program - REST API v2",
"version": "2.0.0"
},
"tags": [
{
"name": "Shop",
"description": "Shop information and authentication"
}
],
"servers": [
{
"url": "https://dev-api.joy.so"
},
{
"url": "https://api.joy.so"
}
],
"paths": {
"/rest_api/v2/whoami": {
"get": {
"tags": [
"Shop"
],
"summary": "Get shop information",
"description": "Retrieve safe shop information for the authenticated shop",
"parameters": [
{
"$ref": "#/components/parameters/AppKeyHeader"
},
{
"$ref": "#/components/parameters/SecretKeyHeader"
}
],
"responses": {
"200": {
"description": "Shop information",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"domain": {
"type": "string"
},
"email": {
"type": "string"
},
"plan": {
"type": "string"
},
"currency": {
"type": "string"
},
"timezone": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"isInstalled": {
"type": "boolean"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
}
}
}
]
}
}
}
}
}
}
}
},
"components": {
"parameters": {
"AppKeyHeader": {
"name": "X-Joy-Loyalty-App-Key",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "App ID of your shop which retrieved from the Settings page"
},
"SecretKeyHeader": {
"name": "X-Joy-Loyalty-Secret-Key",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "Secret Key of your shop which retrieved from the Settings page"
}
},
"schemas": {
"SuccessResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object"
},
"meta": {
"type": "object",
"description": "Additional metadata such as counts and pagination"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
```
--------------------------------
### Optimize API Requests with Pagination and Filters
Source: https://devdocs.joy.so/joy-rest-api-v2/rest-api-v2
Demonstrates efficient data fetching using cursor-based pagination and disabling count metadata to improve performance. Also shows how to filter results using ISO 8601 date strings.
```javascript
// Use hasCount sparingly to avoid performance impact
const customers = await fetch('/rest_api/v2/customers?hasCount=false');
// Navigate using document IDs, not page numbers
const nextPage = await fetch(`/rest_api/v2/customers?after=${lastCustomerId}`);
// Use proper ISO 8601 format for dates
const recentCustomers = await fetch(
'/rest_api/v2/customers?created_at_min=2023-07-01T00:00:00Z'
);
```
--------------------------------
### GET /rest_api/v2/programs/earning/eligibility
Source: https://devdocs.joy.so/joy-rest-api-v2/programs
Retrieves earning programs for a specific customer. Single earn event programs include an 'isEarned' field to indicate if the customer has already completed the action.
```APIDOC
## GET /rest_api/v2/programs/earning/eligibility
### Description
Retrieve earning programs for a specific customer. Single earn event programs (like social media follows, sign up, birthday) will include an `isEarned` field indicating whether the customer has already earned points from that program.
### Method
GET
### Endpoint
/rest_api/v2/programs/earning/eligibility
### Parameters
#### Query Parameters
- **shopifyCustomerId** (string) - Optional - Shopify customer ID. Required if customerId is not provided.
- **customerId** (string) - Optional - Internal customer ID. Required if shopifyCustomerId is not provided.
### Request Example
GET /rest_api/v2/programs/earning/eligibility?shopifyCustomerId=12345
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the request was successful.
- **data** (array) - List of earning programs with eligibility status.
- **meta** (object) - Metadata including the count of programs returned.
#### Response Example
{
"success": true,
"data": [
{
"id": "prog_001",
"title": "Sign up bonus",
"isEarned": true
}
],
"meta": {
"count": 1
}
}
```
--------------------------------
### GET /webhooks
Source: https://devdocs.joy.so/webhook-api/api-reference
Retrieve a list of all registered webhooks associated with the shop.
```APIDOC
## GET /webhooks
### Description
Get a list of all registered webhooks for your shop.
### Method
GET
### Endpoint
https://joy.avada.io/app/api/v1/webhooks
### Parameters
#### Header Parameters
- **X-Joy-Loyalty-App-Key** (string) - Required - Your Joy app key from settings
- **X-Joy-Loyalty-Secret-Key** (string) - Required - Your Joy secret key from settings
### Response
#### Success Response (200)
- **success** (boolean) - Status of the request
- **webhooks** (array) - List of webhook objects
- **timestamp** (string) - ISO 8601 timestamp
#### Response Example
{
"success": true,
"webhooks": [
{
"id": "wh_123",
"topic": "order/created",
"url": "https://example.com/webhook",
"isEnabled": true,
"createdAt": "2023-10-01T12:00:00Z"
}
],
"timestamp": "2023-10-01T12:05:00Z"
}
```
--------------------------------
### Retrieve Branding Settings
Source: https://devdocs.joy.so/joy-javascript-api/joy-loyalty-sdk/public-api-get-methods
Fetches the current branding and configuration settings for the floating widget. This includes color schemes, font settings, and localized labels for the rewards program interface.
```javascript
joyInstance.settingsBranding().then(function(resp){
console.log(resp)
});
```