Sommario
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.
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, SMS, e-mail), 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": [...] }