This guide provides the technical API reference and payload schemas for handling
loyalty programs, memberships, benefits, and reward forecasts in version 2026-04-08 of the Universal Commerce Protocol (UCP).
Before building your endpoints, ensure you have reviewed the Loyalty overview for high-level concepts and dependencies.
Discovery
To support loyalty features, you must advertise the loyalty capability in your UCP profile. Because loyalty benefits often have monetary impacts, you must also enable discounts.
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.common.loyalty": [
{
"version": "2026-04-08",
"extends": [
"dev.ucp.shopping.checkout"
],
"spec": "https://ucp.dev/2026-04-08/specification/loyalty",
"schema": "https://ucp.dev/2026-04-08/schemas/common/loyalty.json"
}
],
"dev.ucp.shopping.discount": [
{
"version": "2026-04-08",
"extends": [
"dev.ucp.shopping.cart",
"dev.ucp.shopping.checkout"
],
"spec": "https://ucp.dev/2026-04-08/specification/discount",
"schema": "https://ucp.dev/2026-04-08/schemas/shopping/discount.json"
}
]
}
}
}
API examples for loyalty
The following examples demonstrate how to handle verified member pricing, and reward earning forecasts.
Verified member pricing
When you verify a user's loyalty membership, apply the unconditional
member-pricing discount (provisional: false) and return a masked
display_id for the membership. Use identity
linking as the primary method
to verify loyalty memberships.
Request example:
{
"line_items": [
{
"item": {
"id": "prod_1"
},
"quantity": 1
}
]
}
Response example:
{
"discounts": {
"applied": [
{
"title": "Loyalty benefit 1",
"amount": 10,
"provisional": false,
"allocations": [
{"path": "$.line_items[0]", "amount": 10}
]
}
]
},
"loyalty": {
"com.example.retail_club": {
"id": "membership_1",
"display_id": "****5678",
"name": "My Loyalty Program",
"tiers": [
{
"id": "tier_1",
"name": "Retail Club Member",
"benefits": [
{
"id": "BEN_001",
"description": "Get $10 off with $500+ purchase."
},
{ "id": "BEN_002", "description": "Early access to sales" }
]
}
],
"provisional": false
}
}
}
Multiple price-impacting benefits
Loyalty can handle multiple memberships simultaneously. In this example, the user receives a 15% bonus discount and free shipping because they hold both the Retail Club membership and the Retail Rewards.
Request example:
{
"line_items": [
{
"item": {
"id": "prod_1"
},
"quantity": 1
}
]
}
Response example:
{
"line_items": [
{
"id": "li_1",
"item": {
"id": "prod_1",
"title": "T-Shirt",
"price": 1000
},
"quantity": 1,
"totals": [
{"type": "subtotal", "amount": 1000},
{
"type": "items_discount",
"display_text": "Club member benefit",
"amount": -150
},
{"type": "total", "amount": 850}
]
}
],
"discounts": {
"applied": [
{
"title": "Club Members get 15% Bonus",
"amount": 150,
"method": "each",
"provisional": false,
"allocations": [
{"path": "$.line_items[0]", "amount": 150}
]
},
{
"title": "Free shipping for Retail Rewards member",
"amount": 199,
"automatic": true,
"provisional": false
}
]
},
"loyalty": {
"com.example.retail_club": {
"id": "membership_1",
"display_id": "****5678",
"name": "Retail Club",
"provisional": false,
"tiers": [
{
"id": "gold",
"name": "Gold Member",
"benefits": [
{ "id": "BEN_001", "description": "Early access to sales" }
]
}
]
},
"com.example.retail_rewards": {
"id": "membership_2",
"display_id": "****1234",
"name": "Retail Rewards",
"provisional": false,
"tiers": [
{
"id": "rewards_member",
"name": "Retail Rewards",
"benefits": [
{ "id": "BEN_002", "description": "Exclusive customer support" }
]
}
]
}
},
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": 1000},
{
"type": "items_discount",
"display_text": "Club member benefit",
"amount": -150
},
{
"type": "discount",
"display_text": "Free shipping for Retail Rewards member",
"amount": -199
},
{"type": "fulfillment", "display_text": "Shipping", "amount": 0},
{"type": "total", "display_text": "Estimated Total", "amount": 651}
]
}
Reward earning forecast
Displaying earnings forecasts helps users understand the value they earn from a
transaction. Use the earning_forecast object to list the total amount of
rewards, and the breakdown array to provide transparency on how you calculated
it.
Request example:
{
"line_items": [
{
"item": {
"id": "prod_1"
},
"quantity": 1
}
]
}
Response example:
{
"line_items": [
{
"id": "li_1",
"item": {
"id": "prod_1",
"title": "T-Shirt",
"price": 1000
},
"quantity": 1,
"totals": [
{"type": "subtotal", "amount": 1000},
{"type": "total", "amount": 1000}
]
}
],
"loyalty": {
"com.example.retail_club": {
"id": "membership_1",
"display_id": "****5678",
"name": "Retail Club",
"provisional": false,
"tiers": [
{
"id": "gold",
"name": "Gold",
"benefits": [
{ "id": "BEN_001", "description": "1 point per $1 on everything" },
{
"id": "BEN_002",
"description": "2 extra point/dollar on footwear"
}
]
}
],
"rewards": [
{
"currency": {
"name": "LoyaltyStars",
"code": "LST"
},
"earning_forecast": {
"amount": 30,
"breakdown": [
{
"id": "RULE_1",
"description": "1 point/dollar on everything",
"amount": 10,
"benefit_id": "BEN_001"
},
{
"id": "RULE_2",
"description": "2 extra point/dollar on footwear",
"amount": 20,
"benefit_id": "BEN_002"
}
]
}
}
]
}
},
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": 1000},
{"type": "total", "display_text": "Estimated Total", "amount": 1000}
]
}