cURL
curl --request POST \
--url https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"enrolled": true,
"customer": {
"state": "enrolled",
"id": 123,
"merchant_id": "<string>",
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"points_approved": 123,
"points_pending": 123,
"points_spent": 123,
"enrolled_at": "<string>",
"tier_membership": {
"tier_id": 123,
"started_at": "2025-01-01T12:00:00Z",
"expires_at": "2026-01-01T12:00:00Z",
"progress": {
"kind": "points",
"valid_until": "<string>",
"points_needed_for_renewal": 123,
"upgrade_tier_id": 123,
"points_needed_for_upgrade": 123,
"tier_points": {
"now": 123,
"at_expiration": 123
},
"forecasted_tier_id": 123
}
},
"birthday": {
"month": 6,
"day": 25
},
"next_birthday": "2025-06-25",
"claimed_rewards": [
{
"id": 123,
"claimed_at": "<string>",
"reward_id": 123,
"title": "$5 voucher",
"state": "approved",
"source": {
"kind": "points_redemption",
"points_cost": 123
},
"auto_refund_at": "<string>",
"redeemable": {
"usage_status": "not_used",
"kind": "gift_card",
"code_last_characters": "<string>",
"initial_balance": {
"amount": 123,
"formatted": "<string>"
},
"current_balance": {
"amount": 123,
"formatted": "<string>"
},
"expires_at": "<string>"
}
}
],
"available_rewards": [
{
"id": 123,
"limit": {
"count": 123,
"interval": "day"
},
"kind": "gift_card",
"properties": {
"initial_balance": {
"amount": 123,
"formatted": "<string>"
}
},
"variant": {
"tier_id": 123,
"title": "$5 voucher",
"description": "Spend your points on $5 off your next order",
"enabled": true,
"cost": {
"kind": "fixed",
"points": 123
},
"cost_text": "100 points"
},
"context": {
"can_redeem": {
"state": "redeemable"
},
"last_claimed_at": "<string>",
"claim_count": 123,
"claim_limit": {
"state": "no_limit"
}
},
"image_url": "<string>"
}
],
"available_rules": [
{
"id": 123,
"limit": {
"count": 123,
"interval": "day"
},
"kind": "birthday",
"variant": {
"tier_id": 123,
"title": "Make a purchase",
"description": "Earn points every time you shop with us",
"enabled": true,
"result": {
"kind": "points",
"per_currency_unit": 1,
"points": 5
},
"result_short_text": "5 points per $1"
},
"context": {
"last_completed_at": "<string>",
"completion_count": 123,
"completion_limit": {
"state": "no_limit"
}
},
"image_url": "<string>"
}
],
"history": [
{
"kind": "earned_points_from_rule",
"label": "Join our program",
"date": "<string>",
"points": 1,
"points_text": "500 points",
"rule": {
"id": 123,
"kind": "birthday"
},
"points_will_approve_at": "<string>",
"points_will_expire_at": "<string>",
"state": "pending"
}
],
"active_cart_redemptions": [
{
"id": "<string>",
"claimed_reward_id": 123,
"expires_at": "<string>",
"product": {
"id": "<string>",
"handle": "<string>",
"title": "<string>",
"url": "<string>",
"image_url": "<string>",
"variant": {
"id": "<string>",
"title": "<string>",
"inventory_count": 123
}
},
"quantity": 123,
"cart_id": "<string>",
"cart_line": {
"kind": "shopify",
"merchandise_id": "gid://shopify/ProductVariant/1001",
"product_id": "gid://shopify/Product/100",
"quantity": 1,
"attributes": [
{
"key": "__lion_sfp_id",
"value": "19fdf4cb"
}
]
},
"current_cart_state": {
"in_cart": true,
"cart_requirements_met": true,
"cart_requirements_detail": {
"minimum_cart_total": {
"state": "no_requirement"
},
"minimum_line_item_quantity": {
"state": "no_requirement"
}
}
}
}
],
"email_marketing_consent": {
"state": "subscribed"
},
"sms_marketing_consent": {
"state": "subscribed"
},
"receipt_upload_url": "<string>",
"referral_urls": {
"direct": "<string>",
"facebook": "<string>",
"twitter": "<string>",
"email": "<string>",
"whatsapp": "<string>",
"instagram": "<string>",
"device_share": "<string>"
}
}
}{
"error": {
"message": "<string>",
"details": {}
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "<string>"
}
}{
"error": {
"code": "customer_blocked",
"message": "<string>"
}
}{
"error": {
"code": "rate_limited"
}
}Customers
Enroll Customer
POST
/
headless
/
2025-06
/
{site_id}
/
customers
/
{merchant_id}
/
enroll
cURL
curl --request POST \
--url https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.loyaltylion.com/headless/2025-06/{site_id}/customers/{merchant_id}/enroll")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"enrolled": true,
"customer": {
"state": "enrolled",
"id": 123,
"merchant_id": "<string>",
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"points_approved": 123,
"points_pending": 123,
"points_spent": 123,
"enrolled_at": "<string>",
"tier_membership": {
"tier_id": 123,
"started_at": "2025-01-01T12:00:00Z",
"expires_at": "2026-01-01T12:00:00Z",
"progress": {
"kind": "points",
"valid_until": "<string>",
"points_needed_for_renewal": 123,
"upgrade_tier_id": 123,
"points_needed_for_upgrade": 123,
"tier_points": {
"now": 123,
"at_expiration": 123
},
"forecasted_tier_id": 123
}
},
"birthday": {
"month": 6,
"day": 25
},
"next_birthday": "2025-06-25",
"claimed_rewards": [
{
"id": 123,
"claimed_at": "<string>",
"reward_id": 123,
"title": "$5 voucher",
"state": "approved",
"source": {
"kind": "points_redemption",
"points_cost": 123
},
"auto_refund_at": "<string>",
"redeemable": {
"usage_status": "not_used",
"kind": "gift_card",
"code_last_characters": "<string>",
"initial_balance": {
"amount": 123,
"formatted": "<string>"
},
"current_balance": {
"amount": 123,
"formatted": "<string>"
},
"expires_at": "<string>"
}
}
],
"available_rewards": [
{
"id": 123,
"limit": {
"count": 123,
"interval": "day"
},
"kind": "gift_card",
"properties": {
"initial_balance": {
"amount": 123,
"formatted": "<string>"
}
},
"variant": {
"tier_id": 123,
"title": "$5 voucher",
"description": "Spend your points on $5 off your next order",
"enabled": true,
"cost": {
"kind": "fixed",
"points": 123
},
"cost_text": "100 points"
},
"context": {
"can_redeem": {
"state": "redeemable"
},
"last_claimed_at": "<string>",
"claim_count": 123,
"claim_limit": {
"state": "no_limit"
}
},
"image_url": "<string>"
}
],
"available_rules": [
{
"id": 123,
"limit": {
"count": 123,
"interval": "day"
},
"kind": "birthday",
"variant": {
"tier_id": 123,
"title": "Make a purchase",
"description": "Earn points every time you shop with us",
"enabled": true,
"result": {
"kind": "points",
"per_currency_unit": 1,
"points": 5
},
"result_short_text": "5 points per $1"
},
"context": {
"last_completed_at": "<string>",
"completion_count": 123,
"completion_limit": {
"state": "no_limit"
}
},
"image_url": "<string>"
}
],
"history": [
{
"kind": "earned_points_from_rule",
"label": "Join our program",
"date": "<string>",
"points": 1,
"points_text": "500 points",
"rule": {
"id": 123,
"kind": "birthday"
},
"points_will_approve_at": "<string>",
"points_will_expire_at": "<string>",
"state": "pending"
}
],
"active_cart_redemptions": [
{
"id": "<string>",
"claimed_reward_id": 123,
"expires_at": "<string>",
"product": {
"id": "<string>",
"handle": "<string>",
"title": "<string>",
"url": "<string>",
"image_url": "<string>",
"variant": {
"id": "<string>",
"title": "<string>",
"inventory_count": 123
}
},
"quantity": 123,
"cart_id": "<string>",
"cart_line": {
"kind": "shopify",
"merchandise_id": "gid://shopify/ProductVariant/1001",
"product_id": "gid://shopify/Product/100",
"quantity": 1,
"attributes": [
{
"key": "__lion_sfp_id",
"value": "19fdf4cb"
}
]
},
"current_cart_state": {
"in_cart": true,
"cart_requirements_met": true,
"cart_requirements_detail": {
"minimum_cart_total": {
"state": "no_requirement"
},
"minimum_line_item_quantity": {
"state": "no_requirement"
}
}
}
}
],
"email_marketing_consent": {
"state": "subscribed"
},
"sms_marketing_consent": {
"state": "subscribed"
},
"receipt_upload_url": "<string>",
"referral_urls": {
"direct": "<string>",
"facebook": "<string>",
"twitter": "<string>",
"email": "<string>",
"whatsapp": "<string>",
"instagram": "<string>",
"device_share": "<string>"
}
}
}{
"error": {
"message": "<string>",
"details": {}
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "<string>"
}
}{
"error": {
"code": "customer_blocked",
"message": "<string>"
}
}{
"error": {
"code": "rate_limited"
}
}Explicitly enroll a customer into the loyalty program. Use this when the shopper
has asked to join, for example by clicking a “Join the program” button in your
storefront or mobile app.
This endpoint bypasses the program’s enrollment strategy entirely, which makes it
the answer for programs configured for opt-in enrollment, where initializing a
session deliberately doesn’t enroll anyone. It’s also safe to call on an
auto-enroll program — calling it for an already-enrolled customer is a no-op.
The customer must already exist in LoyaltyLion. If no customer matches the given
merchant_id, a 404 response will be returned. On a headless storefront running
an opt-in program, the normal sequence is Initialize
Session — which creates a customer who doesn’t exist yet and
leaves them as a guest — then this endpoint once they click join.
The enrolled property is true only when this request performed the
enrollment. If the customer was already a member it will be false and nothing
has changed, so treat it as “did I just enroll them”, not “are they enrolled” —
use customer.state for the latter. The customer property is the customer in
their post-enrollment state.
It’s safe to retry this endpoint, and concurrent calls (e.g. a double-clicked
button, or two open tabs) will only enroll the customer once.
If the customer is blocked from the program, they can’t be enrolled, and a 422
response will be returned with a customer_blocked code.
As with enrollment from a session, enrolling a customer may trigger program
rules, most notably a “join program” rule, if one is configured.Authorizations
ProgramApiKeyCustomerSessionToken
An API key linked to a Program in LoyaltyLion, with a set of permissions (scopes). API keys can be created manually, or acquired through an OAuth2 flow. The API key should be provided as a Bearer token in the Authorization header
Path Parameters
Your LoyaltyLion Site ID
Query Parameters
The sales channel from which this request is made
Available options:
web, pos, mobile ISO 3166-1 alpha-2 country code for the customer. Used to filter rewards by country availability. If not provided, the site default is used
Response
200
A boolean indicating whether this request enrolled the customer. If the customer was already enrolled, this will be false and no other state will have changed
The customer object in its post-enrollment state. If the customer was already enrolled, this represents their existing state
Show child attributes
Show child attributes