Programs
Earning and spending programs management
Get earning programs
Retrieve all earning programs for the authenticated shop
200List of earning programs
trueShow properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseShow properties
Number of items returned
"Operation completed successfully""2023-07-28T07:27:54.123Z"403Plan upgrade required
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"500Internal server error
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"GET /rest_api/v2/programs/earning HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYAccept: */*
{"success": true,"data": [{"id": "prog_earning_001","title": "Sign Up Bonus","description": "Get points for creating an account","type": "earning","event": "sign_up","status": true,"earnPoint": 100,"rateMoney": 1,"priority": 1,"createdAt": "2024-01-15T10:30:00.000Z","updatedAt": "2024-01-20T14:45:30.000Z"},{"id": "prog_earning_002","title": "Place Order Reward","description": "Earn points for every purchase","type": "earning","event": "place_order","status": true,"earnBy": "price","earnPoint": 1,"rateMoney": 1,"appliedPlaceOrderTo": "all","appliedSource": ["web","pos"],"autoRemovePoints": false,"skipEarnPointGuest": false,"roundingMethod": "round","createdAt": "2024-01-10T08:15:00.000Z","updatedAt": "2024-01-25T16:20:45.000Z"}]}
Create earning program
Create a new earning program. The event field determines the program type and which fields are required/validated.
Common required fields (all events): title, event
Common optional fields: status (default varies by event), priority, isDraft, description, startDate, endDate
Event Groups & Required Fields
Simple one-time rewards:
| Event | Required | Optional |
|---|---|---|
sign_up | earnPoint | typeEarn (point / percentage / amount). Percentage: earnPoint <= 100. Discount fields (prefix, appliedTo, expiredAfter, combinedWith) only when typeEarn != "point" |
sign_up_newsletter | earnPoint | autoSyncExistingNewsletter, earnWidgetPopup, excludedSubscribedBefore. Points only (typeEarn forced to "point") |
birthday | earnPoint (unless multi-reward) | typeEarn (point / percentage / amount / bxgy / free_gift), dateFormat (MM/DD, DD/MM, MM/DD/YYYY, DD/MM/YYYY, YYYY/MM/DD), typeDeliveryMethod (automatic / manual), typeRewardTiming (exact_birthday / begin_of_month / around_birthday). around_birthday requires manual delivery |
member_anniversary | earnPoint, duration | duration pattern: "N unit" e.g. "1 Y", "6 M", "30 D". Units: Y, M, D, W, min |
Social engagement (all require earnPoint):
| Event | Required | Optional |
|---|---|---|
like_facebook, follow_instagram, follow_twitter, follow_pinterest, follow_tiktok, subscribe_youtube, join_discord, join_telegram | urlAccount | — |
share_facebook, share_twitter | urlAccount | enabledAntiCheat, message |
join_whatsapp, join_line | typeJoin (link / qr_code) | When link: urlAccount. When qr_code + whatsapp: imageQRCode |
comment_instagram | — | postType (all_posts / specific_posts), keyword filters, auto-reply, DM |
story_mention_instagram | — | DM notification support |
Do NOT send social or action fields — they are auto-derived from event.
Purchase-based:
| Event | Required | Optional |
|---|---|---|
place_order, place_order_subscription | earnPoint | earnBy (price / fixed_order / quantity / order). price: requires rateMoney. quantity: requires rateItem. roundingMethod (roundingNearest / roundingUp / roundingDown), autoRemovePoints, skipEarnPointGuest, rule engine: statusUseCondition, conditions, typeCondition |
typeEarn limited to "point" or "store_credit" for purchase events.
Content & action (all require earnPoint unless noted):
| Event | Required | Optional |
|---|---|---|
write_review | reviewApp (airReviewApp, judgeMeApp, yotpoApp, feraApp, etc.) | Shopify Flow apps also require descriptionReview |
fill_survey | — | link (survey URL, no https:// prefix). earnPoint informational only |
submit_form | — | autoApprove, instantRewardEnabled, instantRewardPoints, requireImage |
submit_receipt | — | Admin approval required. Supports point/percentage/amount |
google_maps_review | urlLocation | isInstantPoint, instantPoint (must be < earnPoint) |
interact_website | — | Uses limitUnit / limitInterval always. Earns once per period |
streak_interact_website | description, startDate, endDate, streakMilestones | streakMilestones: array with day (3/5/7) and earnPoint |
custom_program | typeCustom (visit_page_{id} / completed_profile_{id} / shopify_flow_trigger_{id} / custom_trigger_{id}) | visit_page: linkVisit. completed_profile: fieldProfile (name/email/phone) |
milestone | typeMilestone, milestones (array, min 1) | typeMilestone values: milestone_order, milestone_amount_spent, milestone_earned_point, milestone_reviews, milestone_inactivity, milestone_referral, milestone_subscription |
Date Range (shared)
startDate— optional. If omitted, defaults to current time (program active immediately). Required for streak_interact_website.endDate— optional. If omitted, program never expires. Required for streak_interact_website.- Note: spending programs also default startDate to current time if omitted. They use
expiredAfter/expiredTimefor coupon expiration after redemption.
Earning Frequency (shared across most events)
hasLimit(default varies by event) — enable earning frequency caplimitUnit(minute|hour|day|week|month|year|lifetime, default: "lifetime")limitInterval— required when hasLimit=true AND limitUnit != "lifetime"
VIP Tier Overrides (shared)
isAppliedVipTier(default: false) — enable tier-specific earn ratesearnPointsTiers(object) — tier ID → earnPoint mapping
Program display title
Event type — determines required fields. See endpoint description for details per event.
Whether the program is active. Default varies by event (true for sign_up/place_order, false for social/content events).
Points to award. Required for most events. For percentage typeEarn, must be <= 100.
Reward type. 'point' awards loyalty points. 'percentage'/'amount' create discount coupons. sign_up, member_anniversary, submit_receipt support point/percentage/amount. birthday supports all five types: point, percentage, amount, bxgy, free_gift. place_order only supports point/store_credit.
How points are calculated for place_order events. price: spend $rateMoney earn $earnPoint points. fixed_order: flat points per order (requires rateMoney). quantity: points per item (requires rateItem). order: fixed earnPoint per order.
Currency-to-points ratio. Required when earnBy is 'price' or 'fixed_order'.
Item-to-points ratio. Required when earnBy is 'quantity'.
Social media profile/page URL. Required for simple social, share social events. Must start with http:// or https://.
Google Maps location URL. Required for google_maps_review.
Join method for join_whatsapp, join_line. 'link': urlAccount required. 'qr_code': imageQRCode required (whatsapp only).
QR code image URL. Required when typeJoin='qr_code' and event='join_whatsapp'.
Review app integration. Required for write_review.
Anniversary interval pattern 'N unit' (e.g. '1 Y', '6 M', '30 D', '2 W'). Valid units: Y, M, D, W, min. Required for member_anniversary.
Custom program type '{prefix}_{id}'. Prefixes: visit_page, completed_profile, shopify_flow_trigger, custom_trigger. Required for custom_program.
Milestone trigger type. Required for milestone event.
Milestone thresholds array (min 1). Required for milestone event. Each item: {value, unit? (for inactivity), rewards?, rewardLogic?}.
Show properties
Threshold value
Time unit for milestone_inactivity only
Streak bonus milestones. Required for streak_interact_website. Each: {day: 3|5|7, earnPoint: number}.
Show properties
Rounding for place_order point calculations.
Remove earned points on order refund. For place_order.
Skip earning for guest customers. For place_order.
Who can earn from place_order.
Enable earning frequency cap.
Full enum shown. Some events restrict to subset: social events allow day-lifetime only, birthday allows year/lifetime only, place_order allows minute-lifetime.
Number of limitUnit periods. Required when hasLimit=true AND limitUnit != 'lifetime'.
Enable tier-specific earn rates. When true, use earnPointsTiers to override earnPoint per tier.
Tier-specific earn rates. Keys are tier IDs, values are earnPoint overrides.
Program priority order. Lower numbers = higher priority.
Save as draft without activating.
Program activation date (ISO 8601). If omitted, defaults to current time (program active immediately). Required for streak_interact_website.
Program expiration date (ISO 8601). If omitted, program never expires. Required for streak_interact_website.
Program description shown to customers. Used by social, submit_form, streak_interact_website, and other events.
Anti-cheat verification. Used by share social, comment_instagram, story_mention_instagram, write_review, place_order, custom_program.
Discount code prefix. For discount typeEarn (percentage/amount).
Discount product scope. For discount typeEarn.
Discount coupon expiration. For discount typeEarn.
Discount combination rules. For discount typeEarn.
Sale channel for discount coupons. For discount typeEarn (percentage/amount).
Who can use the coupon. For discount typeEarn.
Collection IDs. Required when appliedTo='specific'. For discount typeEarn.
Product objects (max 100). Required when appliedTo='sf_product'. For discount typeEarn.
Product IDs (max 100). For discount typeEarn.
Order requirement for discount. For discount typeEarn.
Min order amount. Required when orderReq='min_amount'.
Min order quantity. Required when orderReq='min_quantity'.
Specific expiration datetime. Required when expiredAfter='specific'.
Whether to use prefix for discount codes. For discount typeEarn.
Birthday date format. For birthday event.
Reward delivery method. For birthday event. 'around_birthday' timing requires 'manual'.
When to deliver birthday reward. 'around_birthday' only available with typeDeliveryMethod='manual'.
Enable multi-reward layout (customer picks between point/discount/free_gift). For birthday.
Share message text. For share_facebook, share_twitter.
Target posts. For comment_instagram. When 'specific_posts': specificPostIds required.
Instagram post IDs. Required when postType='specific_posts'.
Enable keyword inclusion filter. For comment_instagram.
Required keywords. Required when enableIncludeKeywords=true.
Enable keyword exclusion filter. For comment_instagram.
Blocked keywords. Required when enableExcludeKeywords=true.
Auto-reply to Instagram comments. For comment_instagram.
Auto-reply message. Supports {points} placeholder. Required when enableAutoReply=true.
Send DM notification. For comment_instagram, story_mention_instagram.
DM message text. Supports {points}, {store_url}. Required when enableDMNotification=true.
Review description. Required for Shopify Flow review apps: stampedApp, looxApp, okendoApp, ReviewsIoApp, growaveApp, typdalApp.
Award bonus points for media attachments. For write_review.
Bonus points for media. Required when isAppliedExtraPoints=true (except reviewRocketApp).
Auto-approve form submissions. For submit_form. If false, admin reviews before points awarded.
Award partial points immediately when autoApprove=false. For submit_form.
Partial points to award immediately. Required when autoApprove=false AND instantRewardEnabled=true.
Require image upload. For submit_form.
Award partial points before admin approval. For google_maps_review.
Partial points (must be < earnPoint). Required when isInstantPoint=true.
Page URL to visit. Required when typeCustom starts with 'visit_page'.
Profile fields to complete. Required when typeCustom starts with 'completed_profile'.
Retroactively award points to existing subscribers. For sign_up_newsletter.
Enable rule engine conditions. For place_order.
Rule engine conditions array. For place_order when statusUseCondition=true.
Products to exclude from earning. For place_order.
Products to include for earning. For place_order.
Include shipping fee in points calculation. For place_order.
Include tax in points calculation. For place_order.
Exclude gift card products. For place_order.
Cap maximum points per order. For place_order.
Max points per order. Required when enabledMaxEarnPoint=true.
Exclude free gift items from earning. For place_order.
Exclude store credit items from earning. For place_order.
Product condition matching mode. 'all' = all conditions must match, 'any' = any condition matches. For place_order with rule engine.
Condition type for rule engine. For place_order.
Date range type. 'static_date': uses startDate/endDate. 'dynamic_date': uses valueDateRange. For place_order.
Dynamic date range filter. For place_order with typeDateRange='dynamic_date'.
Rule execution priority (lower = higher). For place_order V2 rule engine.
Stop evaluating lower-priority rules after this rule matches. For place_order V2.
Order tags to exclude from earning. For place_order.
Enable widget popup for newsletter sign-up. For sign_up_newsletter.
Exclude customers who subscribed before program activation. For sign_up_newsletter.
Survey URL (without https:// prefix). For fill_survey.
Bonus points for image attachments. For write_review.
Bonus points for video attachments. For write_review.
How bonus points are calculated. 'per_attachment': multiply by count. 'fixed': flat bonus. For write_review.
Require minimum review length. For write_review.
Minimum character count. Required when enabledMinCharacters=true.
Require minimum star rating. For write_review.
Minimum star rating (1-5). Required when enableMinStarRating=true.
201Program created successfully
trueLoyalty program (earning or spending) with all fields that may be returned by the API. Note: Actual responses may only include non-null fields due to automatic filtering.
Show properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"400Validation error — missing required fields, invalid values, or constraint violations
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"403Plan upgrade required
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"409Duplicate program. Single-instance events allow only one program per shop. **Single-instance events** (1 per shop): sign_up, sign_up_newsletter, birthday, like_facebook, share_facebook, follow_instagram, follow_twitter, share_twitter, follow_pinterest, follow_tiktok, subscribe_youtube, join_discord, join_telegram, join_whatsapp, interact_website, streak_interact_website **Multi-instance events** (no limit): place_order, milestone, custom_program, submit_form, write_review, fill_survey, submit_receipt, member_anniversary, google_maps_review, comment_instagram, story_mention_instagram, join_line
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"POST /rest_api/v2/programs/earning HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 90{"title": "Sign Up Bonus","event": "sign_up","earnPoint": 100,"status": true}
{"success": true,"data": {"id": "pR7mKxQ2wT4vN9yB3jL6","title": "Follow us on Instagram","type": "earning","event": "follow_instagram","status": true,"earnPoint": 50,"social": "instagram","action": "follow","urlAccount": "https://instagram.com/yourshop","hasLimit": true,"limitUnit": "lifetime","isAppliedVipTier": false,"priority": 0,"isDraft": false,"createdAt": "2026-03-24T10:30:00.000Z","updatedAt": "2026-03-24T10:30:00.000Z"},"meta": {},"timestamp": "2026-03-24T10:30:00.123Z"}
Get programs by customer eligibility
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.
Customer Identifier Required: Must provide either customerId or shopifyCustomerId parameter.
Shopify customer ID
Internal customer ID
200Programs for customer with earned status
trueShow properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseOnly present for single earn event programs (social media follows, sign up, birthday, etc.). Indicates if customer has earned from this program.
Show properties
Number of items returned
"Operation completed successfully""2023-07-28T07:27:54.123Z"404Customer not found
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"GET /rest_api/v2/programs/earning/eligibility HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYAccept: */*
{"success": true,"data": [{"id": "prog_earning_001","title": "Sign Up Bonus","type": "earning","event": "sign_up","earnPoint": 100,"isEarned": true,"createdAt": "2024-01-15T10:30:00.000Z","updatedAt": "2024-01-20T14:45:30.000Z"},{"id": "prog_earning_002","title": "Place Order","type": "earning","event": "place_order","earnPoint": 10,"createdAt": "2024-01-16T08:00:00.000Z","updatedAt": "2024-01-21T10:15:00.000Z"},{"id": "prog_earning_003","title": "Follow Instagram","type": "earning","event": "follow_instagram","earnPoint": 50,"isEarned": false,"createdAt": "2024-01-16T12:00:00.000Z","updatedAt": "2024-01-21T16:30:00.000Z"}]}
Calculate earning points
Calculate points that would be earned for given products
Show properties
200Calculated points
trueShow properties
Additional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"POST /rest_api/v2/programs/earning/points/calculate HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 154{"products": [{"id": "string","quantity": 1,"price": 1}],"shopifyCustomerId": "string","sourceName": "string"}
{"success": true,"data": {"pointsEarn": 1,"products": [{}]},"meta": {},"message": "Operation completed successfully","timestamp": "2023-07-28T07:27:54.123Z"}
Handle social earning interactions
Process social media interactions for earning points
200Social earning processed
trueAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"POST /rest_api/v2/programs/earning/social/interactions HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 81{"shopifyCustomerId": "string","event": "string","earningId": "string"}
{"success": true,"data": {},"meta": {},"message": "Operation completed successfully","timestamp": "2023-07-28T07:27:54.123Z"}
Get redemption programs
Retrieve all point spending/redemption programs
Shopify customer ID for program limitations
Filter by program event type
200List of spending programs
trueShow properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseShow properties
Number of items returned
"Operation completed successfully""2023-07-28T07:27:54.123Z"GET /rest_api/v2/programs/redemption HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYAccept: */*
{"success": true,"data": [{"id": "aYorhxYUTkUKIDZgL1R5","title": "Free Product Test","type": "spending","event": "free_gift","status": true,"spendPoint": 200,"earnAmount": 700,"priority": 0,"redeemType": "fixed","appliedTo": "sf_product","redeemIn": "available_in_online_store","expiredTime": "","userAvailability": "userRedeemed","showLoyaltyPage": true,"limitRedeem": "redeemWithoutLimit","totalLimitationRedeem": 0,"combinedWith": ["orderDiscounts","productDiscounts","shippingDiscounts"],"specificProductIds": [44438017147115,44438017114347],"variantIds": [44438017147115,44438017179883,44438017245419,44438017114347],"specificProducts": [{"id": 8209413669099,"title": "The Complete Snowboard","handle": "the-complete-snowboard","image": {"src": "https://cdn.shopify.com/s/files/1/0680/3950/8203/products/Main_589fc064-24a2-4236-9eaf-13b2bd35d21d.jpg?v=1703045153"}}],"giftStatus": "none","expired": false,"isDraft": false,"createdAt": "2024-08-27T08:09:46.757Z","updatedAt": "2025-06-18T08:13:55.797Z"},{"id": "vIswMZYogmKyw94GzEvn","title": "Points for discounts","type": "spending","event": "amount_discount","status": true,"spendPoint": 100,"earnAmount": "5","priority": 3,"redeemType": "fixed","appliedTo": "sf_product","orderReq": "none","orderReqAmount": 0,"expiredTime": "","userAvailability": "userRedeemed","showLoyaltyPage": true,"limitRedeem": "redeemWithoutLimit","combinedWith": [],"specificProductIds": [44438017114347],"conditions": [{"type": "criteria_customer","field": "customer_country_code","typeMatch": "equal"}],"giftStatus": "none","expired": false,"isDraft": false,"createdAt": "2024-10-14T04:36:02.987Z","updatedAt": "2025-06-18T08:13:55.283Z"}]}
Create spending/redemption program
Create a new spending/redemption program. The event field determines the redemption type.
Event Types & Required Fields
amount_discount / percentage_discount:
- Required:
title,event,spendPoint(positive int),earnAmount(discount value; for percentage must be < 100) - Optional:
redeemType(fixed|dynamic, default: "fixed"). Dynamic mode (amount_discount only) lets customer choose points to spend within min/max range. - Dynamic mode fields:
hasMinSpend,minSpendPoint(must be divisible by spendPoint)hasMaxSpend,maxSpendPoint(must be >= spendPoint, divisible by spendPoint)hasLimitCartValue,limitCartValue(1-100, max % of cart)
- Product scope (
appliedTo):all— no extra fieldsspecificorexclude_collection— requiresappliedCollectionIdssf_product— requiresspecificProducts(max 100)
- Order requirements (
orderReq):none— no requirementmin_amount— requiresorderReqAmountmin_quantity— requiresorderReqQuantity
- Expiration:
expiredAfter(permanent|7D|14D|1M|3M|6M|1Y|2Y|specific). When "specific":expiredTimerequired. - Combination:
combinedWith(array of orderDiscounts|productDiscounts|shippingDiscounts). - Availability:
userAvailability(allUsers|userRedeemed|userInSegment). When "userInSegment":appliedSegmentsrequired. - Channel:
appliedDiscountToSaleChannel(applyOnlineStore|applyPos|applyAll).
free_shipping:
- Required:
title,event,spendPoint,shippingDiscountType(percentage|fixedAmount),shippingDiscountAmount(for percentage, must be <= 100) - Optional:
hasLimitShipping,limitShipping(max shipping cost),destination(all|countries),selectedCountries. - Note:
combinedWithcannot include "shippingDiscounts" (this IS a shipping discount).
free_gift:
- Required:
title,event,spendPoint,appliedTo(sf_product|specific|exclude_collection — "all" NOT allowed) - Scope depends on
appliedTo:sf_product— requiresspecificProducts(1-100 items)specificorexclude_collection— requiresappliedCollectionIds+collectionQuantity
- Optional:
variantIds,freeGiftPriceSelection(highest|lowest),freeProductQuantity(all|one).
buy_x_get_y:
- Required:
title,event,spendPoint - Buy-side:
orderReqQuantity(buy X items)appliedTo(specific | sf_product — "all" NOT allowed)- specific →
appliedCollectionIdsrequired - sf_product →
specificProductsrequired
- Get-side:
orderGetQuantity(get Y items)appliedToGets(specific | sf_product)- specific →
appliedCollectionIdsGetsrequired - sf_product →
specificProductsGetsrequired
discountedType(percentage | amount | free). When percentage/amount →discountedValuerequired.
custom_voucher: (hidden feature, not recommended)
- Required:
title,event,spendPoint - Optional:
descriptionHtml,imageUrl,newVouchers(array of voucher codes),voucherLimitRedeem.
Shared Optional Fields
status(default: true),priority,isDraft,prefix,isUsePrefixDiscountCode,showLoyaltyPagehasLimit,limitUnit,limitInterval— redemption frequency capusageLimit,appliesOncePerCustomer— Shopify discount usage limitscustomerEligibility(eligible_all|eligible_tier_customer),tiersEligible
Program display title shown to customers.
Spending event type. Determines required fields and validation rules.
Whether the program is active.
Points required to redeem. Required for all events.
Discount value. Required for amount_discount/percentage_discount. For percentage, must be < 100.
fixed: set points for set discount. dynamic: customer chooses within min/max range.
Required for free_shipping.
Shipping discount value. Required for free_shipping. For percentage, must be <= 100.
Product scope. For free_gift: 'all' NOT allowed.
Collection IDs. Required when appliedTo is 'specific' or 'exclude_collection'.
Product objects (max 100). Required when appliedTo is 'sf_product'.
Order requirement to use reward. 'min_amount': customer order must exceed orderReqAmount. 'min_quantity': order must have at least orderReqQuantity items.
Min order amount. Required when orderReq='min_amount'.
Min item quantity. Required when orderReq='min_quantity'. For buy_x_get_y: number of items customer must buy.
Number of free/discounted items customer gets. Required for buy_x_get_y.
Get-side product scope for buy_x_get_y. 'specific': use appliedCollectionIdsGets. 'sf_product': use specificProductsGets.
Discount applied to get-side items. 'free': 100% off. 'percentage'/'amount': requires discountedValue. Required for buy_x_get_y.
Discount value on get-side items. Required when discountedType is 'percentage' or 'amount'.
Coupon expiration period. 'permanent': never expires. 'specific': use expiredTime for exact datetime.
Allow combining with other Shopify discount types. For free_shipping: cannot include 'shippingDiscounts'.
Which sales channels the coupon is valid on.
Who can redeem. 'allUsers': everyone. 'userRedeemed': only loyalty members. 'userInSegment': requires appliedSegments.
Program display order. Lower = higher priority.
Save as draft without activating.
Discount code prefix.
Whether to use prefix for discount codes.
Show on loyalty/rewards page.
Specific expiration datetime. Required when expiredAfter='specific'.
Which purchase types the discount applies to. Only visible when shop.enableDiscountSubscription is enabled. For amount_discount/percentage_discount.
Advanced discount conditions. Customer-level conditions for all events; order-level (order_shipping_method) only for free_shipping. Requires Advanced plan.
Show properties
Allow checkout-page redemption. Requires Shopify Plus and Enterprise/Pro plan.
Exclude specific POS locations.
POS location IDs to exclude.
Where the program is displayed. For POS-enabled programs.
Restrict to specific VIP tiers. For amount_discount/percentage_discount.
Tier IDs that can access this program. Used when isAppliedVipTier=true.
Per-tier overrides for spend/earn values. Format: { [tierId]: { earnPoint, spendPoint, earnAmount } }. Used when isAppliedVipTier=true.
Enable minimum spend in dynamic mode. For amount_discount with redeemType='dynamic'.
Min points to spend (must be divisible by spendPoint). Required when hasMinSpend=true.
Enable maximum spend in dynamic mode.
Max points (must be >= spendPoint, divisible by spendPoint). Required when hasMaxSpend=true.
Limit discount to percentage of cart value.
Max percentage of cart value for discount (1-100). Required when hasLimitCartValue=true.
Prevent reuse of cart-value-limited coupons on smaller carts. Recommended when hasLimitCartValue=true.
Apply only to shipping rates below max cost. For free_shipping.
Max shipping cost. Required when hasLimitShipping=true.
Shipping destination scope. For free_shipping.
Country filter. Required when destination='countries'.
Product variant IDs for the buy side. Required when appliedTo='sf_product' for buy_x_get_y.
Collection objects (for display). Used alongside appliedCollectionIds.
Show properties
Specific variant IDs (max 100). For free_gift with appliedTo='sf_product'.
Which product price to select from collection. For free_gift with appliedTo='specific'/'exclude_collection'.
Whether customer gets all listed products or picks one. For free_gift.
Total quantity of free products across collections. Required for free_gift when appliedTo='specific'/'exclude_collection'.
Get-side collection IDs. Required when appliedToGets='specific'.
Get-side products (max 100). Required when appliedToGets='sf_product'.
Get-side product variant IDs. Required when appliedToGets='sf_product'.
Get-side collection objects (for display). Used alongside appliedCollectionIdsGets.
Cap uses per order. For buy_x_get_y.
Max uses per order. Required when enableMaximumUsesPerOrder=true.
Rich-text HTML description shown to customers. For custom_voucher.
Voucher image URL. For custom_voucher.
Voucher codes to import (duplicates auto-removed, existing codes skipped). For custom_voucher.
Max vouchers a single customer can redeem. null/omit = unlimited. For custom_voucher.
Start date for voucher redemption period (ISO 8601). For custom_voucher.
End date for voucher redemption period (ISO 8601). Must be after expDateFrom. For custom_voucher.
Segment filter. Required when userAvailability='userInSegment'.
Shopify discount usage limit.
Limit to one use per customer.
Customer eligibility filter.
Tier IDs. Required when customerEligibility='eligible_tier_customer'.
Enable redemption frequency cap.
Time unit for frequency cap.
Number of limitUnit periods between redemptions. Required when hasLimit=true AND limitUnit != 'lifetime'.
Global redemption limit type.
Total redemption limit. Required when limitRedeem='redeemLimit'.
201Program created successfully
trueLoyalty program (earning or spending) with all fields that may be returned by the API. Note: Actual responses may only include non-null fields due to automatic filtering.
Show properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"400Validation error — missing required fields, invalid values, or cross-field constraint violations
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"POST /rest_api/v2/programs/redemption HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 317{"title": "Points for $5 off","event": "amount_discount","spendPoint": 100,"earnAmount": 5,"redeemType": "fixed","appliedTo": "all","orderReq": "min_amount","orderReqAmount": 25,"expiredAfter": "3M","combinedWith": ["shippingDiscounts"],"prefix": "REWARD-","status": true}
{"success": true,"data": {"id": "xK9mNpQ2wR4vT7yB3jL6","title": "Points for $5 off","type": "spending","event": "amount_discount","status": true,"spendPoint": 100,"earnAmount": 5,"priority": 0,"redeemType": "fixed","appliedTo": "all","orderReq": "min_amount","orderReqAmount": 25,"expiredAfter": "3M","userAvailability": "userRedeemed","showLoyaltyPage": true,"combinedWith": ["shippingDiscounts"],"appliedDiscountToSaleChannel": "applyOnlineStore","purchaseType": "one_time_purchase","prefix": "REWARD-","isUsePrefixDiscountCode": true,"isDraft": false,"createdAt": "2026-03-24T10:30:00.000Z","updatedAt": "2026-03-24T10:30:00.000Z"},"meta": {},"timestamp": "2026-03-24T10:30:00.123Z"}
Get program by ID
Retrieve a specific program by its ID
Program ID
Shopify customer ID for program limitations
200Program details
trueLoyalty program (earning or spending) with all fields that may be returned by the API. Note: Actual responses may only include non-null fields due to automatic filtering.
Show properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"404Program not found
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"GET /rest_api/v2/programs/{programId} HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYAccept: */*
{"success": true,"data": {"id": "aYorhxYUTkUKIDZgL1R5","title": "Free Product Test","type": "spending","event": "free_gift","status": true,"spendPoint": 200,"earnAmount": 700,"priority": 0,"redeemType": "fixed","appliedTo": "sf_product","redeemIn": "available_in_online_store","expiredTime": "","userAvailability": "userRedeemed","showLoyaltyPage": true,"limitRedeem": "redeemWithoutLimit","totalLimitationRedeem": 0,"combinedWith": ["orderDiscounts","productDiscounts","shippingDiscounts"],"specificProductIds": [44438017147115,44438017114347],"variantIds": [44438017147115,44438017179883,44438017245419,44438017114347],"specificProducts": [{"id": 8209413669099,"title": "The Complete Snowboard","handle": "the-complete-snowboard","image": {"src": "https://cdn.shopify.com/s/files/1/0680/3950/8203/products/Main_589fc064-24a2-4236-9eaf-13b2bd35d21d.jpg?v=1703045153"},"variants": [{"id": 44438017147115,"price": "700","title": "Ice","inventory_quantity": 10}]}],"giftStatus": "none","expired": false,"isDraft": false,"createdAt": "2024-08-27T08:09:46.757Z","updatedAt": "2025-06-18T08:13:55.797Z"}}
Update program
Partial update — send only the fields you want to change. The endpoint looks up the program, determines its type (earning or spending), and filters the update body to only fields allowed for that type. Unrecognized or readonly fields are silently ignored.
Behavior
- Readonly fields stripped:
id,type,shopId,createdAt,updatedAtare always ignored — you cannot change a program's type or ID. - Field whitelist applied: Only fields in
earningProgramFields(for earning) orspendingProgramFields(for spending) pass through. Other fields are silently dropped. - Empty body rejected: Returns 400
UPDATE_DATA_REQUIREDif the request body is empty. - No valid fields rejected: Returns 400
INVALID_UPDATE_FIELDSif all provided fields were readonly or not in the whitelist. - Response: Returns the full updated program (re-fetched after save), with null fields filtered out and dates formatted.
Updatable Fields by Program Type
Earning programs — any field from earningProgramFields (see POST /programs/earning):
| Category | Fields |
|---|---|
| Basic | title, status, earnPoint, priority, isDraft, startDate, endDate |
| Purchase | earnBy, rateMoney, autoRemovePoints, appliedPlaceOrderTo, appliedSource, excludeProducts, includeProducts, conditions, roundingMethod, skipEarnPointGuest |
| Social | urlAccount, enabledAntiCheat, message, typeJoin, imageQRCode |
| Review | reviewApp, descriptionReview, isAppliedExtraPoints, extraPoints |
| Frequency | hasLimit, limitUnit, limitInterval |
| VIP Tier | isAppliedVipTier, earnPointsTiers |
| Discount (typeEarn != point) | prefix, isUsePrefixDiscountCode, appliedTo, appliedCollectionIds, specificProducts, orderReq, orderReqAmount, expiredAfter, expiredTime, combinedWith, appliedDiscountToSaleChannel, userAvailability |
Spending programs — any field from spendingProgramFields (see POST /programs/redemption):
| Category | Fields |
|---|---|
| Basic | title, status, spendPoint, earnAmount, redeemType, priority, isDraft |
| Product scope | appliedTo, appliedCollectionIds, specificProducts, specificProductIds, specificCollections, variantIds |
| Order requirements | orderReq, orderReqAmount, orderReqQuantity |
| Dynamic mode | minSpendPoint, maxSpendPoint, hasMinSpend, hasMaxSpend, hasLimitCartValue, limitCartValue |
| Expiration | expiredAfter, expiredTime |
| Limits | limitRedeem, totalLimitationRedeem, usageLimit, appliesOncePerCustomer, blockLimitedCouponReuse, hasLimit, limitInterval, limitUnit |
| Availability | userAvailability, appliedSegments, customerEligibility, tiersEligible, showLoyaltyPage |
| Discount config | combinedWith, appliedDiscountToSaleChannel, purchaseType, prefix, isUsePrefixDiscountCode, isRedeemCheckOut, enabledExcludePOS, excludeLocationsPOS |
Important Notes
- You cannot change
eventortype— these are set at creation time. - No cross-field validation is applied on update (unlike create). The provided fields are saved as-is.
- For spending programs,
spendPointis cast to integer in the response viaprepareProgramData.
Program ID
Program display title.
Enable/disable the program.
Points to award. For earning programs.
Points required to redeem. For spending programs.
Discount value. For spending programs (amount_discount, percentage_discount).
Program display/sort priority.
Toggle draft mode.
Earning method. For place_order programs.
Currency-to-points ratio. For place_order with earnBy=price/fixed_order.
Social media URL. For social earning programs.
Program start date (ISO 8601). For earning programs.
Program end date (ISO 8601). For earning programs.
Remove points on refund. For place_order.
Point rounding. For place_order.
Skip guest earning. For place_order.
Redemption mode. For amount_discount.
Product scope. For discount/free_gift programs.
Collection IDs. For programs with appliedTo=specific.
Product objects. For programs with appliedTo=sf_product.
Order requirement.
Minimum order amount.
Coupon expiration. For spending programs.
Specific expiration datetime.
Discount combination rules.
Sales channel for discount.
Who can use the discount.
Purchase type filter.
Shopify discount usage limit. null = unlimited.
Limit to one use per customer.
Enable earning/redeem frequency cap.
Frequency cap time unit.
Frequency cap interval.
Enable VIP tier restrictions.
Per-tier earn/spend overrides.
Discount code prefix.
Whether to use prefix.
Allow checkout-page redemption.
Exclude POS locations.
POS location IDs to exclude.
Customer eligibility filter. For spending programs.
Tier IDs for eligibility.
Advanced conditions.
Show on loyalty page.
Enable min spend (dynamic discount).
Enable max spend (dynamic discount).
Minimum points to spend.
Maximum points to spend.
Limit discount to % of cart.
Max % of cart value (1-100).
Prevent cart-limited coupon reuse.
Customer segments for userInSegment.
200Program updated successfully. Returns the full updated program.
trueLoyalty program (earning or spending) with all fields that may be returned by the API. Note: Actual responses may only include non-null fields due to automatic filtering.
Show properties
"prog_abc123""Sign Up Bonus""earning""sign_up"true1"2024-01-15T10:30:00.000Z""2024-01-20T14:45:30.000Z"falsefalse"price"1100"2024-01-01T00:00:00.000Z""2024-12-31T23:59:59.000Z"false"all"["web","pos"]{}null[]50010"amount_discount""all"[]"available_in_online_store""none"0"""""""userRedeemed"true"redeemWithoutLimit"0[][][][][][]"none"Show properties
Show properties
Show properties
Show properties
Show properties
"round"falseAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"400Invalid update data or no valid fields for program type
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"404Program not found
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"PUT /rest_api/v2/programs/{programId} HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 22{"earnPoint": 200}
{"success": true,"data": {"id": "vIswMZYogmKyw94GzEvn","title": "Points for discounts","type": "spending","event": "amount_discount","status": true,"spendPoint": 200,"earnAmount": 10,"priority": 3,"redeemType": "fixed","appliedTo": "all","orderReq": "none","expiredAfter": "6M","userAvailability": "userRedeemed","showLoyaltyPage": true,"combinedWith": [],"appliedDiscountToSaleChannel": "applyOnlineStore","purchaseType": "one_time_purchase","isDraft": false,"createdAt": "2024-10-14T04:36:02.987Z","updatedAt": "2026-03-24T11:00:00.000Z"},"meta": {},"timestamp": "2026-03-24T11:00:00.123Z"}
Delete program (hard delete)
Permanently removes a program from the database. This action cannot be undone.
The response includes the full program data as it existed before deletion, allowing the caller to store a backup if needed.
Program ID
200Program deleted successfully
trueFull program data as it existed before deletion
Show properties
Additional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"404Program not found
falseShow properties
"Resource not found""NOT_FOUND"404"2023-07-28T07:27:54.123Z"DELETE /rest_api/v2/programs/{programId} HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYAccept: */*
{"success": true,"data": {"id": "prog_abc123","title": "Earn on Purchase","event": "place_order","type": "earning","status": true},"message": "Program deleted successfully"}
Redeem points for rewards
Redeem customer points for rewards through a redemption program
200Redemption successful
trueAdditional metadata such as counts and pagination
"Operation completed successfully""2023-07-28T07:27:54.123Z"POST /rest_api/v2/programs/redemption/redeem HTTP/1.1Host: dev-api.joy.soX-Joy-Loyalty-App-Key: YOUR_API_KEYX-Joy-Loyalty-Secret-Key: YOUR_API_KEYContent-Type: application/jsonAccept: */*Content-Length: 77{"programId": "string","shopifyCustomerId": "string","quantity": 1}
{"success": true,"data": {},"meta": {},"message": "Operation completed successfully","timestamp": "2023-07-28T07:27:54.123Z"}