報酬定義ガイド reward-definition-guide

このページでは、​報酬プロバイダーと報酬の定義の設定方法、報酬JSONata式の作成方法、フルフィルメント ペイロードの生成に使用されるコンテキストの理解方法について説明します。

チャレンジタスク、マイルストーン、またはチャレンジが​ を完了し、報酬値が設定されている ​場合、プラットフォームは報酬プロバイダーのHTTP エンドポイントをJSON ペイロードで呼び出すことによって報酬を発行します。 報酬定義​は、発行する報酬を表し、プロバイダーが期待する正確なペイロードを形成するJSONata式rewardJsonataを提供します。

このガイドでは、報酬プロバイダーの設定、報酬の定義の作成、rewardJsonata式の記述、評価時に利用可能なコンテキストの把握について説明します。

➡️ ​ ロイヤルティ報酬プロバイダーの設定方法を見る

2 レベルモデル

報酬は、次の2つのレベルで構成されています。

Reward Provider  (endpoint, auth, headers)
└── Reward Definition  (denomination, rewardJsonata)
└── Reward Definition
└── ...

報酬プロバイダー​は、単一の外部報酬システムを表します。配信エンドポイント URL、認証、およびカスタム HTTP ヘッダーを保持します。 1つのプロバイダーには、複数の​ 報酬定義 ​を保持でき、各プロバイダーが提供する報酬タイプまたは名称(例:「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 なし(システム割り当て) 一意のID: 読み取り専用:
name String はい 組織内で一意の表示名。
desc String × プロバイダーの人間が判読可能な説明。
enabled Boolean × falseの場合、このプロバイダーのすべての定義に対する特典配信は
中断されます。
url String はい 報酬ペイロードを受信するHTTP エンドポイント。
プラットフォームは、このURLに対して評価された
rewardJsonata出力をPOSTします。
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 なし(システム割り当て) 一意のID: 読み取り専用:
name String はい プロバイダー内で一意の表示名。
denomination String × 表示
で使用され、式
reward.denomination
で使用可能な報酬の単位(例:"Stars"、"Points"、"Miles")。
desc String × 報酬の説明。式で
をreward.descとして使用できます。
enabled Boolean × falseの場合、この定義は非アクティブであり
報酬を発行しません。
isDefault Boolean × これをサンドボックス全体のデフォルト
の報酬定義としてマークします。 すべてのプロバイダーで一度に1つの定義
のみをデフォルトにできます。
新しいデフォルトを設定すると、前の定義が消去されます。
公開時にパーソナライズされた課題
に関する報酬の詳細を自動入力するために使用されます。
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
{
  "memberId":   challenge.profileId,
  "points":     $number(rewardContext.rewardValue),
  "currency":   reward.denomination
}

出力:

code language-json
{
  "memberId": "ADB-0000030",
  "points":   50,
  "currency": "Stars"
}

rewardContext.rewardValueは常に文字列です。 プロバイダーが数値を想定している場合は、$number()を使用して変換します。

プロバイダー固有のメタデータにkvpCustomを使用しています

多くの場合、プロバイダーは、課題の実行ごとに固有のキャンペーン IDやソースシステムコードなどのフィールドを必要とします。 チャレンジのオーサリング時にこれらをchallenge.kvpCustomに保存し、その後、それらをエクスプレッションで参照することで、キャンペーン全体でエクスプレッションを再利用できます。

code language-jsonata
{
  "memberId":         challenge.profileId,
  "points":           $number(rewardContext.rewardValue),
  "campaignId":       challenge.kvpCustom.campaignId,
  "transactionSource": "AJO"
}

また、チャレンジ単位ではなく、特定の報酬タイプに固定された定数に対してreward.kvpCustomを使用することもできます。

タスクアキュムレーターデータの使用

タスクのアキュムレータには、選定イベントごとにレコードが保持されます。 item_list[-1]を使用して、最近適用された項目にアクセスします。このtransactionIdとtimestampは、プロバイダー側での監査証跡と重複排除に役立ちます。

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "transactionId":  task.accumulators.item_list[-1].transactionId,
  "transactionDate": task.accumulators.item_list[-1].timestamp
}
テキストメッセージの作成

通知ベースのプロバイダー(Slack、モバイルメッセージ、メール)の場合、JSONataの&連結演算子を使用してメッセージ文字列を直接作成できます。

code language-jsonata
{
  "text": "You just earned " & rewardContext.rewardValue & " " & reward.denomination & "!"
}

出力:

code language-json
{
  "text": "You just earned 50 Stars!"
}

例

例1 — シンプルなポイントプロバイダー

シナリオ:​基本的なロイヤルティポイント APIでは、メンバーIDとポイント額が必要です。

報酬の定義:

code language-json
{
  "name":         "Standard Points",
  "denomination": "Points",
  "desc":         "Award loyalty points",
  "enabled":      true,
  "rewardJsonata": "{\"memberId\": challenge.profileId, \"pointQuantity\": $number(rewardContext.rewardValue), \"denomination\": reward.denomination}"
}

形式の式:

code language-jsonata
{
  "memberId":      challenge.profileId,
  "pointQuantity": $number(rewardContext.rewardValue),
  "denomination":  reward.denomination
}

ペイロードがプロバイダー​にPOSTされました

code language-json
{
  "memberId":      "ADB-0000030",
  "pointQuantity": 50,
  "denomination":  "Points"
}
例2 — キャンペーンメタデータを含むプロバイダーペイロード

シナリオ:​このプロバイダーには、監査フィールド、キャンペーン参照、メンバーの説明を含む構造化アワードレコードが必要です。 キャンペーン固有の値はchallenge.kvpCustomに保存されるため、式を編集することなく、同じ報酬の定義がキャンペーン間で機能します。

チャレンジkvpCustom (チャレンジのオーサリング時に設定):

code language-json
{
  "parentCampaignId": "CAMP-2026-Q1",
  "productName":      "Loyalty Program"
}

報酬の定義:

code language-json
{
  "name":         "Stars — Campaign Award",
  "denomination": "Stars",
  "desc":         "Issue Stars for completing a qualifying purchase",
  "enabled":      true,
  "rewardJsonata": "{\"awardPoints\":[{\"idType\":\"externalId\",\"id\":challenge.profileId,\"transactionId\":task.accumulators.item_list[-1].transactionId,\"transactionDate\":task.accumulators.item_list[-1].timestamp,\"originalTransactionId\":task.accumulators.item_list[-1].transactionId,\"transactionSource\":\"AJO\",\"channelSource\":\"Web\",\"parentCampaignId\":challenge.kvpCustom.parentCampaignId,\"productName\":challenge.kvpCustom.productName,\"memberAwardDescription\":reward.desc,\"pointQuantity\":$number(rewardContext.rewardValue)}]}"
}

形式の式:

code language-jsonata
{
  "awardPoints": [
    {
      "idType":                "externalId",
      "id":                    challenge.profileId,
      "transactionId":         task.accumulators.item_list[-1].transactionId,
      "transactionDate":       task.accumulators.item_list[-1].timestamp,
      "originalTransactionId": task.accumulators.item_list[-1].transactionId,
      "transactionSource":     "AJO",
      "channelSource":         "Web",
      "parentCampaignId":      challenge.kvpCustom.parentCampaignId,
      "productName":           challenge.kvpCustom.productName,
      "memberAwardDescription": reward.desc,
      "pointQuantity":         $number(rewardContext.rewardValue)
    }
  ]
}

ペイロードがプロバイダー​にPOSTされました

code language-json
{
  "awardPoints": [
    {
      "idType":                "externalId",
      "id":                    "ADB-0000030",
      "transactionId":         "b4fa0e89-f4bb-41ce-b370-fb97f9c52f1a",
      "transactionDate":       "2026-02-08T00:12:00.000+00:00",
      "originalTransactionId": "b4fa0e89-f4bb-41ce-b370-fb97f9c52f1a",
      "transactionSource":     "AJO",
      "channelSource":         "Web",
      "parentCampaignId":      "CAMP-2026-Q1",
      "productName":           "Loyalty Program",
      "memberAwardDescription": "Issue Stars for completing a qualifying purchase",
      "pointQuantity":         50
    }
  ]
}
例3 - マイルストーン報酬

シナリオ: ストリーク チャレンジでは、N回の訪問ごとにマイルストーン報酬が発行されます。 この式には、マイルストーン数と、プロバイダーサイドのコンテキストの現在のストリークが含まれます。

形式の式:

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "milestoneCount": milestone.count,
  "currentStreak":  task.schedule.currentStreak,
  "denomination":   reward.denomination,
  "source":         rewardContext.source
}

ペイロードがプロバイダー​にPOSTされました(2回目の訪問マイルストーン時):

code language-json
{
  "memberId":       "ADB-0000030",
  "points":         20,
  "milestoneCount": 2,
  "currentStreak":  2,
  "denomination":   "Stars",
  "source":         "milestone"
}

rewardContext.sourceが"milestone"の場合、milestone オブジェクトにはcountとreward.rewardValueが入力されます。 ソースが"task"または"challenge"の場合、milestoneはnullです。

API リファレンス

報酬プロバイダー
code language-http
POST   /loyalty/metadata/config/rewards/providers
GET    /loyalty/metadata/config/rewards/providers
GET    /loyalty/metadata/config/rewards/providers/{providerId}
PUT    /loyalty/metadata/config/rewards/providers/{providerId}
DELETE /loyalty/metadata/config/rewards/providers/{providerId}

すべてのリクエストにはx-gw-ims-org-idおよびx-sandbox-name個のヘッダーが必要です。

プロバイダーの作成:

code language-http
POST /loyalty/metadata/config/rewards/providers
x-gw-ims-org-id: {ORG_ID}
x-sandbox-name: {SANDBOX}
Content-Type: application/json

{
  "name":    "My Points Provider",
  "desc":    "Issues loyalty points via REST",
  "enabled": true,
  "url":     "https://rewards.example.com/award",
  "additionalHeaders": {
    "x-api-key": "YOUR_API_KEY"
  }
}
報酬定義
code language-http
POST   /loyalty/metadata/config/rewards/definitions/{providerId}
GET    /loyalty/metadata/config/rewards/definitions/{providerId}
GET    /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}
PUT    /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}
DELETE /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}

報酬の定義を作成:

code language-http
POST /loyalty/metadata/config/rewards/definitions/{providerId}
x-gw-ims-org-id: {ORG_ID}
x-sandbox-name: {SANDBOX}
Content-Type: application/json

{
  "name":         "50 Stars",
  "denomination": "Stars",
  "desc":         "Award 50 Stars on task completion",
  "enabled":      true,
  "rewardJsonata": "{ \"memberId\": challenge.profileId, \"points\": $number(rewardContext.rewardValue) }"
}

式の検証

rewardJsonata式は、公開時に構文が検証されます。 式が無効な場合、APIは解析エラーの説明を含む422 エラーを返します。

公開前に式を開発してテストするには、JSONata Exerciserを使用します。 報酬コンテキスト JSONを入力ドキュメントとして貼り付け、出力がプロバイダーが期待するものと一致することを確認します。 各トリガータイプ (task、milestone、challenge)の代表的な報酬コンテキストを上記の例に示します。

よくある間違い

失敗
エフェクト
修正
コンバージョンなしでrewardContext.rewardValueが数値として使用されました
プロバイダーがフィールドを数値として検証する場合、タイプが一致しません
$number(rewardContext.rewardValue)で終了
challenge.kvpCustom.someKeyがnullを返します
オーサリング時にチャレンジにキーが設定されていません
この定義を使用するすべてのチャレンジでkvpCustomにキーが存在することを確認します
task.accumulators.item_list[-1]はnullです
特典が発行される前にアイテムが適用されませんでした(非購入イベント)
条件付きで監視するか、代わりにコンテキストからtimestampを使用します
ソースが"task"または"challenge"の場合、milestoneにアクセスしました
milestoneはnullです。式はnull フィールドをスローまたは生成します
milestoneにアクセスする前にrewardContext.sourceを確認するか、マイルストーン報酬に添付された定義でmilestoneのみを使用してください
式は、オブジェクトではなく配列を返します
プロバイダーが予期しないペイロード構造を受信しました
配列を返す式を外部オブジェクトで折り返します:{ "items": [...] }

チュートリアルビデオ video

➡️ ロイヤルティ報酬プロバイダーの設定方法を見る

AI Knowledge Reference

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:

  • name and url are required fields on a reward provider; guid is system-assigned and read-only.
  • name and rewardJsonata are required fields on a reward definition; guid is system-assigned and read-only.
  • When a reward provider’s enabled field is false, reward delivery is suspended for all definitions under that provider.
  • When a reward definition’s enabled field 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.
  • maxRatePerSecond on a reward provider accepts a value from 1 to 5000 (per provider); null means unlimited.
  • rewardContext.rewardValue is always a string; it must be converted with $number() if the provider expects a numeric value.
  • milestone is null when the reward source is "task" or "challenge"; it is populated (with count and reward.rewardValue) only when rewardContext.source is "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.someKey returns 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? — name and url are required; guid is system-assigned and read-only.
  • Q: What fields are required to create a reward definition? — name and rewardJsonata are required; guid is 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), and reward.denomination into a memberId/points/currency object, producing {"memberId": "ADB-0000030", "points": 50, "currency": "Stars"}.
  • Using kvpCustom: an expression references challenge.kvpCustom.campaignId alongside challenge.profileId and rewardContext.rewardValue to keep the expression reusable across campaigns.
  • Using task accumulator data: an expression uses task.accumulators.item_list[-1].transactionId and .timestamp for 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), and reward.denomination to memberId, pointQuantity, and denomination, producing a payload with pointQuantity: 50.
  • Example 2 — Provider payload with campaign metadata: a Reward Definition builds an awardPoints array using challenge.kvpCustom.parentCampaignId and challenge.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.count and task.schedule.currentStreak; when rewardContext.source is "milestone", the milestone object is populated with count and reward.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.
recommendation-more-help
journey-optimizer-help