Guida alla definizione del premio reward-definition-guide

In questa pagina: Scopri come configurare provider di premi e definizioni di premi, scrivere espressioni JSONata di ricompensa e comprendere il contesto utilizzato per generare payload di evasione.

Quando un’attività di verifica, un’attività cardine o una sfida completa e ha un valore di ricompensa configurato, la piattaforma emette una ricompensa chiamando l’endpoint HTTP del provider di ricompensa con un payload JSON. Una definizione premio descrive il premio da emettere e fornisce un’espressione JSONata, rewardJsonata, che definisce il payload esatto previsto dal provider.

Questa guida illustra come configurare un provider di premi, creare definizioni di premi, scrivere l’espressione rewardJsonata e capire il contesto disponibile al momento della valutazione.

➡️ Guarda come impostare un provider di premi fedeltà

Modello a due livelli

I premi sono organizzati in due livelli:

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

Un Provider di premi rappresenta un singolo sistema di premi esterno. Contiene l’URL dell’endpoint di consegna, l’autenticazione ed eventuali intestazioni HTTP personalizzate. Un provider può contenere più Definizioni di ricompensa, ognuna delle quali descrive un tipo di ricompensa o una denominazione distinta offerta dal provider (ad esempio “50 Stelle”, “Stelle doppie”, “Elemento libero”).

Una richiesta di verifica fa riferimento al provider e alla definizione per GUID. Quando viene assegnato un premio, la piattaforma valuta l’espressione rewardJsonata della definizione e PUBBLICA il risultato sull’endpoint del provider.

Campi di definizione e provider di premi

Campi del provider di premi
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
Campo Tipo Obbligatorio Descrizione
guid String No (assegnato dal sistema) Identificatore univoco. Sola lettura.
name String Sì Nome visualizzato, univoco all’interno dell’organizzazione.
desc String No Descrizione leggibile del provider.
enabled Boolean No Quando false, la consegna dei premi è
sospesa per tutte le definizioni in questo provider.
url String Sì Endpoint HTTP che riceve il payload di ricompensa.
La piattaforma invia l'output
rewardJsonata valutato a questo URL.
additionalHeaders Object No Intestazioni HTTP personalizzate da includere in ogni
richiesta di consegna (ad esempio chiavi API,
sostituzioni di tipo contenuto).
maxRatePerSecond Integer No Limite di tariffa per provider facoltativo (1-5000).
Null significa illimitato.
enableMTLS Boolean No Se l’endpoint richiede TLS reciproco.
Campi di definizione del premio
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
Campo Tipo Obbligatorio Descrizione
guid String No (assegnato dal sistema) Identificatore univoco. Sola lettura.
name String Sì Nome visualizzato, univoco all’interno del provider.
denomination String No Unità del premio, utilizzata in visualizzazione
e disponibile nelle espressioni come
reward.denomination
(ad esempio "Stars", "Points", "Miles").
desc String No Descrizione del premio, disponibile
nelle espressioni come reward.desc.
enabled Boolean No Quando false, questa definizione è inattiva
e non emetterà premi.
isDefault Boolean No Contrassegna questo come definizione di ricompensa predefinita
a livello di sandbox. È possibile impostare una sola definizione
per tutti i provider alla volta;
l'impostazione di un nuovo valore predefinito cancella quello precedente.
Utilizzato per popolare automaticamente i dettagli dei premi sulle
sfide personalizzate al momento della pubblicazione.
rewardJsonata String Sì Espressione JSONata valutata
al momento del problema del premio. Riceve il contesto completo
di ricompensa e deve restituire il payload JSON
a POST al provider.

Contesto del premio

Quando rewardJsonata viene valutato, riceve un singolo oggetto principale contenente tutto ciò che è noto sull’evento di ricompensa. Tutti i percorsi nell’espressione sono relativi a questa radice.

{
  "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"
}
Campi contestuali
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
Campo Descrizione
rewardContext.rewardValue Stringa di valore del premio configurata per la sfida, l’attività o l’attività cardine che ha attivato l’emissione.
rewardContext.source Che cosa ha attivato il premio: "task", "challenge" o "milestone".
reward La stessa RewardDefinition: name, desc, denomination.
task L’attività di completamento, inclusi accumulators, schedule e reward.
task.accumulators.spend Spesa totale qualificata accumulata dall’attività.
task.accumulators.qty Numero totale di articoli qualificati accumulato dall’attività.
task.accumulators.item_list Tutti gli elementi idonei applicati all’attività. Ogni voce ha item, transactionId, timestamp, utcOffset, locationId.
task.accumulators.item_list[-1] L’elemento più recente applicato (indice JSONata negativo). Utile per determinare l’origine dell’ID o della marca temporale dell’ultima transazione.
task.schedule.currentStreak Conteggio attuale delle sequenze di visite consecutive (per le sfide di serie).
task.schedule.currentVisits Conteggio totale delle visite (per le sfide relative alle visite).
milestone La milestone che ha attivato questo premio, o null se non è un premio milestone. Include count e reward.rewardValue.
challenge.profileId ID fedeltà del membro.
challenge.kvpCustom Coppie chiave-valore personalizzate configurate per la sfida. Un modello comune per il passaggio di ID campagna, nomi di prodotto o metadati specifici del provider.
challenge.name Nome della sfida.
challenge._id ID sfida.
timestamp Timestamp ISO 8601 dell’emissione del premio.

Scrittura dell’espressione rewardJsonata

L’espressione riceve il contesto di ricompensa come input e deve restituire un oggetto JSON, il payload POSTed all’endpoint del provider. La forma di tale oggetto dipende interamente dall’API del provider. I campi contestuali vengono mappati in base alla struttura prevista dal provider.

Payload fisso semplice

Il caso più semplice: il provider richiede un conteggio dei punti e un ID membro, entrambi noti dal contesto.

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

Output:

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

rewardContext.rewardValue è sempre una stringa. Utilizza $number() per convertirlo se il provider prevede un valore numerico.

Utilizzo di kvpCustom per metadati specifici del provider

I provider spesso richiedono campi come ID campagna o codici del sistema sorgente specifici per ogni sfida eseguita. Memorizza questi elementi in challenge.kvpCustom durante l’authoring della sfida, quindi fai riferimento ad essi nell’espressione, mantenendo l’espressione riutilizzabile nelle campagne.

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

È inoltre possibile utilizzare reward.kvpCustom per le costanti fisse per un determinato tipo di premio anziché per sfida.

Utilizzo dei dati accumulatori delle attività

Gli accumulatori di task tengono traccia di ogni evento qualificato. Utilizza item_list[-1] per accedere all’elemento applicato più di recente. I relativi transactionId e timestamp sono utili per gli audit trail e la deduplicazione sul lato provider.

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "transactionId":  task.accumulators.item_list[-1].transactionId,
  "transactionDate": task.accumulators.item_list[-1].timestamp
}
Creazione di un messaggio di testo

Per i provider basati su notifiche (Slack, mobile message, email), puoi creare una stringa di messaggio direttamente utilizzando l’operatore di concatenazione & di JSONata:

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

Output:

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

Esempi

Esempio 1 — Fornitore di punti semplice

Scenario: un’API di base per i punti fedeltà prevede un ID membro e una quantità di punti.

Definizione premio:

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}"
}

Espressione formattata:

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

Payload inviato al provider:

code language-json
{
  "memberId":      "ADB-0000030",
  "pointQuantity": 50,
  "denomination":  "Points"
}
Esempio 2 — Payload del provider con metadati della campagna

Scenario: Il provider richiede un record di riconoscimento strutturato che includa campi di controllo, riferimenti alla campagna e descrizione del membro. I valori specifici della campagna sono archiviati in challenge.kvpCustom, pertanto la stessa definizione del premio funziona nelle campagne senza modificare l’espressione.

SfidakvpCustom (impostata durante l’authoring della sfida):

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

Definizione premio:

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)}]}"
}

Espressione formattata:

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)
    }
  ]
}

Payload inviato al provider:

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
    }
  ]
}
Esempio 3 — Premio Milestone

Scenario: una sfida di tipo streak genera un premio milestone ogni N visite. L’espressione include il conteggio delle milestone e la sequenza corrente per il contesto lato provider.

Espressione formattata:

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

Payload POST inviato al provider (alla seconda visita):

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

Quando rewardContext.source è "milestone", l’oggetto milestone viene popolato con count e reward.rewardValue. Quando l’origine è "task" o "challenge", milestone è null.

Documentazione delle API

Provider di premi
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}

Tutte le richieste richiedono x-gw-ims-org-id e x-sandbox-name intestazioni.

Crea un provider:

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"
  }
}
Definizioni dei premi
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}

Creare una definizione di premio:

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) }"
}

Convalida espressione

rewardJsonata espressioni sono convalidate per la sintassi al momento della pubblicazione. Se l’espressione non è valida, l’API restituisce un errore 422 con una descrizione dell’errore di analisi.

Per sviluppare e testare un’espressione prima della pubblicazione, utilizzare l’JSONata Exerciser. Incolla il JSON del contesto di ricompensa come documento di input e l’espressione per verificare che l’output corrisponda a quello previsto dal provider. Negli esempi precedenti viene mostrato un contesto di ricompensa rappresentativo per ogni tipo di trigger (task, milestone, challenge).

Errori comuni

Errore
Effetto
Correggi
rewardContext.rewardValue utilizzato come numero senza conversione
Tipo non corrispondente se il provider convalida il campo come numerico
A capo con $number(rewardContext.rewardValue)
challenge.kvpCustom.someKey restituisce null
Chiave non impostata sulla sfida al momento dell’authoring
Assicurarsi che la chiave sia presente in kvpCustom per ogni sfida che utilizza questa definizione
task.accumulators.item_list[-1] è nullo
Nessun elemento applicato prima del premio emesso (evento non di acquisto)
Controlla con un condizionale o utilizza timestamp dal contesto
Accesso a milestone eseguito quando l’origine è "task" o "challenge"
milestone è null; l’espressione genera o produce campi null
Controlla rewardContext.source prima di accedere a milestone oppure utilizza solo milestone nelle definizioni allegate ai premi milestone
L’espressione restituisce un array invece di un oggetto
Il provider riceve una struttura di payload imprevista
Racchiudi espressioni che restituiscono array in un oggetto esterno: { "items": [...] }

Video dimostrativi video

➡️ Scopri come impostare un provider di premi fedeltà

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