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
| 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. |
| 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 è inattivae 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"
}
| 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.
Il caso più semplice: il provider richiede un conteggio dei punti e un ID membro, entrambi noti dal contesto.
| code language-jsonata |
|---|
|
Output:
| code language-json |
|---|
|
rewardContext.rewardValueè sempre una stringa. Utilizza$number()per convertirlo se il provider prevede un valore numerico.
kvpCustom per metadati specifici del providerI 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 |
|---|
|
È inoltre possibile utilizzare reward.kvpCustom per le costanti fisse per un determinato tipo di premio anziché per sfida.
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 |
|---|
|
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 |
|---|
|
Output:
| code language-json |
|---|
|
Esempi
Scenario: un’API di base per i punti fedeltà prevede un ID membro e una quantità di punti.
Definizione premio:
| code language-json |
|---|
|
Espressione formattata:
| code language-jsonata |
|---|
|
Payload inviato al provider:
| code language-json |
|---|
|
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 |
|---|
|
Definizione premio:
| code language-json |
|---|
|
Espressione formattata:
| code language-jsonata |
|---|
|
Payload inviato al provider:
| code language-json |
|---|
|
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 |
|---|
|
Payload POST inviato al provider (alla seconda visita):
| code language-json |
|---|
|
Quando
rewardContext.sourceè"milestone", l’oggettomilestoneviene popolato concountereward.rewardValue. Quando l’origine è"task"o"challenge",milestoneènull.
Documentazione delle API
| code language-http |
|---|
|
Tutte le richieste richiedono x-gw-ims-org-id e x-sandbox-name intestazioni.
Crea un provider:
| code language-http |
|---|
|
| code language-http |
|---|
|
Creare una definizione di premio:
| code language-http |
|---|
|
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
rewardContext.rewardValue utilizzato come numero senza conversione$number(rewardContext.rewardValue)challenge.kvpCustom.someKey restituisce nullkvpCustom per ogni sfida che utilizza questa definizionetask.accumulators.item_list[-1] è nullotimestamp dal contestomilestone eseguito quando l’origine è "task" o "challenge"milestone è null; l’espressione genera o produce campi nullrewardContext.source prima di accedere a milestone oppure utilizza solo milestone nelle definizioni allegate ai premi milestone{ "items": [...] }Video dimostrativi video
➡️ Scopri come impostare un provider di premi fedeltà
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.