在此頁面上:瞭解如何設定獎勵提供者和獎勵定義、撰寫獎勵JSONata運算式,以及瞭解用來產生履行裝載的內容。
當挑戰任務、里程碑或挑戰完成 並設定了獎勵值 時,平台會呼叫您的獎勵提供者的HTTP端點並使用JSON裝載來發出獎勵。 獎勵定義說明問題的獎勵,並提供JSONata運算式 — rewardJsonata — 以圖形化您的提供者所期望的確切裝載。
本指南涵蓋如何設定獎勵提供者、建立獎勵定義、撰寫rewardJsonata運算式,以及瞭解評估時可供使用的內容。
雙層模型
獎勵分為兩個層級:
Reward Provider (endpoint, auth, headers)
└── Reward Definition (denomination, rewardJsonata)
└── Reward Definition
└── ...
獎勵提供者代表單一外部獎勵系統 — 它包含傳遞端點URL、驗證及任何自訂HTTP標頭。 一個提供者可以保留多個獎勵定義,每個定義都描述該提供者提供的不同獎勵型別或面額(例如「50顆星」、「雙顆星」、「免費專案」)。
質詢會依據GUID參考提供者和定義。 當發出獎勵時,平台會評估定義的rewardJsonata運算式,並將結果POST至提供者的端點。
獎勵提供者與定義欄位
| table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 5-row-4 6-row-4 7-row-4 8-row-4 html-authored | |||
|---|---|---|---|
| 欄位 | 類型 | 必要 | 說明 |
guid |
String |
否(系統指派) | 唯一識別碼。 唯讀。 |
name |
String |
是 | 顯示名稱,組織內唯一。 |
desc |
String |
無 | 提供者可讀取的說明。 |
enabled |
Boolean |
無 | 當false時,已針對此提供者下的所有定義暫停獎勵傳遞。 |
url |
String |
是 | 接收獎勵裝載的HTTP端點。 平台POST將評估過的 rewardJsonata輸出傳至此URL。 |
additionalHeaders |
Object |
無 | 自訂HTTP標頭,可包含在每 個傳遞要求中(例如API金鑰、 內容型別覆寫)。 |
maxRatePerSecond |
Integer |
無 | 選擇性的每個提供者速率限制(1-5000)。 Null表示無限制。 |
enableMTLS |
Boolean |
無 | 端點是否需要雙向TLS。 |
| table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 5-row-4 6-row-4 7-row-4 html-authored | |||
|---|---|---|---|
| 欄位 | 類型 | 必要 | 說明 |
guid |
String |
否(系統指派) | 唯一識別碼。 唯讀。 |
name |
String |
是 | 顯示名稱,在提供者中唯一。 |
denomination |
String |
無 | 獎勵的單位,用於顯示 ,可在運算式中作為 reward.denomination使用(例如 "Stars"、"Points"、"Miles")。 |
desc |
String |
無 | 獎勵的說明,可在運算式中以reward.desc形式取得。 |
enabled |
Boolean |
無 | 當false時,此定義為非使用中且不會發出獎勵。 |
isDefault |
Boolean |
無 | 將此專案標籤為沙箱範圍的預設 獎勵定義。 所有提供者一次只能有一個定義 是預設值; 設定新的預設值會清除上一個定義。 用於在發佈時自動填入 個人化挑戰的獎勵詳細資料。 |
rewardJsonata |
String |
是 | JSONata運算式在 獎勵問題時間評估。 接收完整 獎勵內容,且必須將JSON 裝載傳回至POST給提供者。 |
獎勵內容
評估rewardJsonata時,它會收到包含獎勵事件所有已知內容的單一根物件。 運算式中的所有路徑都與此根相關。
{
"rewardContext": {
"rewardValue": "50",
"source": "challenge"
},
"reward": {
"name": "500 Stars",
"desc": "Issue 500 Stars to the member",
"denomination": "Stars",
"enabled": true
},
"task": { ... },
"milestone": { ... },
"challenge": { ... },
"timestamp": "2026-02-10T00:29:22.538+00:00"
}
| table 0-row-2 1-row-2 2-row-2 3-row-2 4-row-2 5-row-2 6-row-2 7-row-2 8-row-2 9-row-2 10-row-2 11-row-2 12-row-2 13-row-2 14-row-2 15-row-2 16-row-2 | |
|---|---|
| 欄位 | 說明 |
rewardContext.rewardValue |
在觸發此發行的挑戰、任務或里程碑上設定的獎勵值字串。 |
rewardContext.source |
觸發獎勵的專案: "task"、"challenge"或"milestone"。 |
reward |
RewardDefinition本身 — name、desc、denomination。 |
task |
完成的工作,包括其accumulators、schedule和reward。 |
task.accumulators.spend |
任務累積的合格總支出。 |
task.accumulators.qty |
任務累積的合格專案總數。 |
task.accumulators.item_list |
套用至任務的所有合格專案。 每個專案都有item、transactionId、timestamp、utcOffset、locationId。 |
task.accumulators.item_list[-1] |
最近套用的專案(JSONata負索引)。 對於取得最後一個交易ID或時間戳記非常有用。 |
task.schedule.currentStreak |
目前的連續造訪連續計數(針對連續挑戰)。 |
task.schedule.currentVisits |
造訪總數(針對造訪挑戰)。 |
milestone |
觸發此獎勵的里程碑;若不是里程碑獎勵,則為null。 包含count和reward.rewardValue。 |
challenge.profileId |
成員的熟客ID。 |
challenge.kvpCustom |
在挑戰設定的自訂索引鍵值配對。 傳遞行銷活動ID、產品名稱或提供者專用中繼資料的常見模式。 |
challenge.name |
挑戰名稱。 |
challenge._id |
挑戰ID。 |
timestamp |
獎勵簽發的ISO 8601時間戳記。 |
撰寫rewardJsonata運算式
運算式會接收獎勵內容作為其輸入,且必須傳回JSON物件 — 裝載已對提供者的端點進行POST。 該物件的形狀完全取決於提供者的API;您可以將內容欄位對應到提供者期望的任何結構。
最簡單的情況:提供者需要點數和成員ID,兩者都從內容中得知。
| code language-jsonata |
|---|
|
輸出:
| code language-json |
|---|
|
rewardContext.rewardValue永遠是字串。 如果您的提供者需要數值,請使用$number()進行轉換。
kvpCustom提供者通常需要行銷活動ID或原始系統程式碼等欄位,這些欄位是每個挑戰執行所專屬。 編寫挑戰時將這些專案儲存在challenge.kvpCustom中,然後在運算式中參照它們 — 讓運算式可跨行銷活動重複使用。
| code language-jsonata |
|---|
|
您也可以將reward.kvpCustom用於固定特定獎勵型別(而非每個挑戰)的常數。
任務累計器會儲存每個合格事件的記錄。 使用item_list[-1]存取最近套用的專案 — 其transactionId和timestamp對於提供者端的稽核追蹤和重複資料刪除很有用。
| code language-jsonata |
|---|
|
對於通知型提供者(Slack、行動訊息、電子郵件),您可以使用JSONata的&串連運運算元直接建置訊息字串:
| code language-jsonata |
|---|
|
輸出:
| code language-json |
|---|
|
範例
案例:基本熟客點數API需要會員ID與點數。
獎勵定義:
| code language-json |
|---|
|
格式化運算式:
| code language-jsonata |
|---|
|
裝載張貼至提供者:
| code language-json |
|---|
|
案例:提供者需要包含稽核欄位、行銷活動參照和成員說明的結構化獎勵記錄。 行銷活動特定值儲存在challenge.kvpCustom中,因此相同的獎勵定義可在行銷活動間運作,而不需編輯運算式。
挑戰kvpCustom (在編寫挑戰時設定):
| code language-json |
|---|
|
獎勵定義:
| code language-json |
|---|
|
格式化運算式:
| code language-jsonata |
|---|
|
裝載張貼至提供者:
| code language-json |
|---|
|
案例: Streak挑戰會每隔N次造訪發出里程碑獎勵。 運算式包含里程碑計數以及提供者端內容的目前連結。
格式化運算式:
| code language-jsonata |
|---|
|
裝載已發佈至提供者 (在第2次造訪里程碑時):
| code language-json |
|---|
|
當
rewardContext.source為"milestone"時,milestone物件會填入count和reward.rewardValue。 當來源是"task"或"challenge"時,milestone是null。
API 參考
| code language-http |
|---|
|
所有要求都需要x-gw-ims-org-id和x-sandbox-name標頭。
建立提供者:
| code language-http |
|---|
|
| code language-http |
|---|
|
建立獎勵定義:
| code language-http |
|---|
|
運算式驗證
rewardJsonata運算式已在發佈時針對語法進行驗證。 如果運算式無效,API會傳回422錯誤,其中包含剖析失敗的描述。
若要在發佈之前開發和測試運算式,請使用JSONata Exerciser。 將獎勵內容JSON貼上為輸入檔案和您的運算式,以驗證輸出符合您的提供者期望。 每個觸發程式型別(task、milestone、challenge)的代表性獎勵內容會顯示在上面的範例中。
常見錯誤
rewardContext.rewardValue已用為數字但未轉換$number(rewardContext.rewardValue)換行challenge.kvpCustom.someKey傳回nullkvpCustom中都存在金鑰task.accumulators.item_list[-1]為nulltimestampmilestone在來源為"task"或"challenge"時存取milestone為空;運算式擲回或產生null欄位milestone前請先檢查rewardContext.source,或僅在附加至里程碑獎勵的定義中使用milestone{ "items": [...] }作法影片 video
➡️觀看如何設定忠誠獎勵提供者
This section contains structured knowledge intended to support interpretation, retrieval, and question answering related to this topic.
For complete understanding, this information should be combined with the documentation on this page. Neither source is intended to stand alone; the page describes the feature, while this section provides additional context that helps disambiguate terminology, intent, applicability, and constraints.
- TL;DR: This page explains how to configure reward providers and reward definitions for Loyalty Challenges, including the fields involved, the reward context passed to the rewardJsonata expression, and how to write that expression to build the payload posted to a reward provider’s endpoint.
Intents:
- Configure a reward provider (endpoint, authentication, headers) and one or more reward definitions under it.
- Understand the fields available on reward providers and reward definitions, including which are required.
- Write a rewardJsonata expression that maps reward context fields onto the payload a provider expects.
- Use kvpCustom on a challenge to pass campaign-specific or provider-specific metadata without editing the expression.
- Use task accumulator data, such as the most recent item in item_list, inside an expression.
- Distinguish task, milestone, and challenge reward sources and access the milestone object correctly.
- Validate a rewardJsonata expression before publishing and troubleshoot common mistakes.
Glossary:
- Reward Provider (product-specific): represents a single external rewards system; holds the delivery endpoint URL, authentication, and custom HTTP headers.
- Reward Definition (product-specific): describes a distinct reward type or denomination offered by a provider, including its rewardJsonata expression.
- rewardJsonata (product-specific): a JSONata expression configured on a reward definition that is evaluated at reward-issue time and must return the JSON payload to POST to the provider.
- Reward context (product-specific): the single root object passed to rewardJsonata at evaluation time, containing rewardContext, reward, task, milestone, challenge, and timestamp.
- kvpCustom (product-specific): custom key-value pairs configured on a challenge (challenge.kvpCustom) or available as constants on a reward (reward.kvpCustom), used to pass campaign IDs, product names, or provider-specific metadata.
- isDefault (product-specific): marks a reward definition as the sandbox-wide default, used to auto-populate reward details on personalized challenges at publish time.
- item_list (product-specific): the list of all qualifying items applied to a task’s accumulators; item_list[-1] accesses the most recently applied item via JSONata negative indexing.
Guardrails:
nameandurlare required fields on a reward provider;guidis system-assigned and read-only.nameandrewardJsonataare required fields on a reward definition;guidis system-assigned and read-only.- When a reward provider’s
enabledfield is false, reward delivery is suspended for all definitions under that provider. - When a reward definition’s
enabledfield is false, that definition is inactive and will not issue rewards. - Only one reward definition across all providers may be marked as default (
isDefault) at a time; setting a new default clears the previous one. maxRatePerSecondon a reward provider accepts a value from 1 to 5000 (per provider); null means unlimited.rewardContext.rewardValueis always a string; it must be converted with$number()if the provider expects a numeric value.milestoneis null when the reward source is"task"or"challenge"; it is populated (withcountandreward.rewardValue) only whenrewardContext.sourceis"milestone".- rewardJsonata expressions are validated for syntax at publish time; an invalid expression causes the API to return a 422 error with a description of the parse failure.
challenge.kvpCustom.someKeyreturns null if the key was not set on the challenge at authoring time.task.accumulators.item_list[-1]is null if no items were applied before the reward was issued (a non-purchase event).- If a rewardJsonata expression returns an array instead of an object, the provider receives an unexpected payload structure; it must be wrapped in an outer object.
Terminology:
- Canonical name: Reward Provider — holds the endpoint, authentication, and headers for an external rewards system.
- Canonical name: Reward Definition — describes a reward type or denomination and its rewardJsonata expression; belongs to one Reward Provider.
- Do not confuse: “Reward Provider” (the external system’s endpoint, auth, and headers) ≠ “Reward Definition” (a specific reward type/denomination with its own rewardJsonata, nested under a provider).
- Do not confuse: “challenge.kvpCustom” (per-challenge custom metadata) ≠ “reward.kvpCustom” (constants fixed for a given reward type).
- Do not confuse:
rewardContext.rewardValue(the reward value string that triggered issuance) ≠milestone.reward.rewardValue(the reward value specific to a milestone).
FAQ:
- Q: What triggers a reward to be issued? — When a challenge task, milestone, or challenge completes and has a reward value configured, the platform issues a reward by calling the reward provider’s HTTP endpoint with a JSON payload.
- Q: What fields are required to create a reward provider? —
nameandurlare required;guidis system-assigned and read-only. - Q: What fields are required to create a reward definition? —
nameandrewardJsonataare required;guidis system-assigned and read-only. - Q: How many reward definitions can be marked as default? — Only one definition across all providers may be default at a time; setting a new default clears the previous one.
- Q: Why does rewardContext.rewardValue need conversion before use as a number? — Because rewardContext.rewardValue is always a string; use $number() to convert it if the provider expects a numeric value.
- Q: Why would challenge.kvpCustom.someKey return null? — Because the key was not set on the challenge at authoring time; ensure the key is present in kvpCustom on every challenge that uses the definition.
- Q: What happens if an invalid rewardJsonata expression is published? — The API returns a 422 error with a description of the parse failure.
- Q: Where can I test a rewardJsonata expression before publishing? — In the JSONata Exerciser, by pasting the reward context JSON as the input document and the expression to verify the output.
Troubleshooting:
task.accumulators.item_list[-1] is null— Cause: no items were applied before the reward was issued (a non-purchase event). Fix: guard with a conditional or use timestamp from context instead.milestone accessed when source is "task" or "challenge"— Cause: milestone is null in that case. Fix: check rewardContext.source before accessing milestone, or only use milestone in definitions attached to milestone rewards.Expression returns an array instead of an object— Cause: the provider receives an unexpected payload structure. Fix: wrap array-returning expressions in an outer object, for example{ "items": [...] }.challenge.kvpCustom.someKey returns null— Cause: the key was not set on the challenge at authoring time. Fix: ensure the key is present in kvpCustom on every challenge that uses this definition.422 error— Cause: the rewardJsonata expression is invalid at publish time. Fix: the API returns a description of the parse failure; use the JSONata Exerciser to develop and test the expression before publishing.
Examples:
- Simple fixed payload: maps
challenge.profileId,$number(rewardContext.rewardValue), andreward.denominationinto a memberId/points/currency object, producing{"memberId": "ADB-0000030", "points": 50, "currency": "Stars"}. - Using kvpCustom: an expression references
challenge.kvpCustom.campaignIdalongsidechallenge.profileIdandrewardContext.rewardValueto keep the expression reusable across campaigns. - Using task accumulator data: an expression uses
task.accumulators.item_list[-1].transactionIdand.timestampfor audit trails and deduplication on the provider side. - Constructing a text message: an expression concatenates strings with
&, for example"You just earned " & rewardContext.rewardValue & " " & reward.denomination & "!", producing{"text": "You just earned 50 Stars!"}. - Example 1 — Simple points provider: a Reward Definition with rewardJsonata mapping
challenge.profileId,$number(rewardContext.rewardValue), andreward.denominationtomemberId,pointQuantity, anddenomination, producing a payload withpointQuantity: 50. - Example 2 — Provider payload with campaign metadata: a Reward Definition builds an
awardPointsarray usingchallenge.kvpCustom.parentCampaignIdandchallenge.kvpCustom.productName(set on the challenge) plus task accumulator transaction data, so the same definition works across campaigns without editing the expression. - Example 3 — Milestone reward: an expression includes
milestone.countandtask.schedule.currentStreak; whenrewardContext.sourceis"milestone", the milestone object is populated withcountandreward.rewardValue.
Personas:
- admin: Can configure a reward provider with its endpoint URL, authentication, and additional headers, and create reward definitions under it. Can set maxRatePerSecond between 1 and 5000, or leave it null for unlimited. Can mark enabled to false on a provider or definition to suspend or stop reward delivery. The page states that only one reward definition across all providers may be isDefault at a time. Where: “Reward provider & definition fields”.
Onboarding:
- Level: Intermediate
- First minimal step: Paste the reward context JSON as the input document in the JSONata Exerciser and add your rewardJsonata expression.
- Success check: The output matches what your provider expects.