Tabla de contenido
Cuando una tarea, hito o desafío de desafío completa y tiene configurado un valor de recompensa, la plataforma emite un incentivo llamando al extremo HTTP del proveedor de recompensas con una carga útil JSON. Una definición de recompensa describe qué recompensa emitir y proporciona una expresión JSONata — rewardJsonata — que define la carga útil exacta que espera su proveedor.
Esta guía explica cómo configurar un proveedor de recompensas, crear definiciones de recompensas, escribir la expresión rewardJsonata y comprender qué contexto está disponible en el momento de la evaluación.
Modelo de dos niveles
Las recompensas se organizan en dos niveles:
Reward Provider (endpoint, auth, headers)
└── Reward Definition (denomination, rewardJsonata)
└── Reward Definition
└── ...
Un proveedor de recompensas representa un único sistema de recompensas externo; contiene la dirección URL del extremo de entrega, la autenticación y cualquier encabezado HTTP personalizado. Un proveedor puede tener varias definiciones de recompensa, cada una de las cuales describe un tipo de recompensa o una denominación distinta que ofrece ese proveedor (por ejemplo, “50 estrellas”, “estrellas dobles”, “artículo gratis”).
Un desafío hace referencia al proveedor y a la definición por GUID. Cuando se emite una recompensa, la plataforma evalúa la expresión rewardJsonata de la definición y PUBLICA el resultado en el extremo del proveedor.
Campos de definición y proveedor de recompensas
| 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 | Requerido | Descripción |
guid |
String |
No (asignado por el sistema) | Identificador único. Sólo lectura. |
name |
String |
Sí | Nombre para mostrar, único dentro de la organización. |
desc |
String |
No | Descripción legible en lenguaje natural del proveedor. |
enabled |
Boolean |
No | Cuando false, la entrega de recompensa sesuspende para todas las definiciones de este proveedor. |
url |
String |
Sí | Punto final HTTP que recibe la carga útil de recompensa. La plataforma publica el resultado evaluado rewardJsonata en esta dirección URL. |
additionalHeaders |
Object |
No | Encabezados HTTP personalizados para incluirlos en cada solicitud de envío (p. ej. claves de API, invalidaciones de tipo de contenido). |
maxRatePerSecond |
Integer |
No | Límite de tarifa opcional por proveedor (1-5000). Nulo significa ilimitado. |
enableMTLS |
Boolean |
No | Si el punto de conexión requiere TLS mutuo. |
| 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 | Requerido | Descripción |
guid |
String |
No (asignado por el sistema) | Identificador único. Sólo lectura. |
name |
String |
Sí | Nombre para mostrar, único dentro del proveedor. |
denomination |
String |
No | La unidad del premio, usada en la pantalla y disponible en expresiones como reward.denomination(p. ej. "Stars", "Points", "Miles"). |
desc |
String |
No | Descripción del premio, disponible en expresiones como reward.desc. |
enabled |
Boolean |
No | Cuando false, esta definición está inactivay no emitirá recompensas. |
isDefault |
Boolean |
No | Marca esto como la definición de recompensa predeterminada para toda la zona protegida . Solo puede haber una definición predeterminada en todos los proveedores a la vez; al establecer una nueva definición predeterminada se borra la anterior. Se usa para rellenar automáticamente los detalles de recompensa en desafíos personalizados en el momento de la publicación. |
rewardJsonata |
String |
Sí | Expresión JSONata evaluada en momento de recompensa por el problema. Recibe el contexto de recompensa completo y debe devolver la carga útil JSON para POST al proveedor. |
El contexto de recompensa
Cuando se evalúa rewardJsonata, recibe un único objeto raíz que contiene todo lo conocido sobre el evento de recompensa. Todas las rutas de la expresión son relativas a esta raíz.
{
"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 | Descripción |
rewardContext.rewardValue |
Cadena de valor de recompensa configurada en el desafío, tarea o hito que activó esta emisión. |
rewardContext.source |
Qué activó la recompensa: "task", "challenge" o "milestone". |
reward |
La propia RewardDefinition: name, desc, denomination. |
task |
La tarea de finalización, incluidos sus accumulators, schedule y reward. |
task.accumulators.spend |
Gasto total correspondiente acumulado por la tarea. |
task.accumulators.qty |
Recuento total de artículos aptos acumulado por la tarea. |
task.accumulators.item_list |
Todos los elementos aptos aplicados a la tarea. Cada entrada tiene item, transactionId, timestamp, utcOffset, locationId. |
task.accumulators.item_list[-1] |
El elemento aplicado más recientemente (índice negativo de JSONata). Útil para obtener el último ID de transacción o la última marca de tiempo. |
task.schedule.currentStreak |
Recuento de racha de visitas consecutivas actuales (para desafíos de racha). |
task.schedule.currentVisits |
Recuento total de visitas (para los desafíos de visita). |
milestone |
El hito que generó esta recompensa o null, si no es una recompensa de hito. Incluye count y reward.rewardValue. |
challenge.profileId |
ID de fidelidad del miembro. |
challenge.kvpCustom |
Pares de clave-valor personalizados configurados en el desafío. Un patrón común para pasar ID de campaña, nombres de productos o metadatos específicos de proveedores. |
challenge.name |
Nombre del desafío. |
challenge._id |
ID de desafío. |
timestamp |
Marca de tiempo ISO 8601 de la emisión de recompensa. |
Escritura de la expresión de premio Jsonata
La expresión recibe el contexto de recompensa como entrada y debe devolver un objeto JSON (la carga útil POST) al extremo del proveedor. La forma de ese objeto depende totalmente de la API del proveedor; los campos de contexto se asignan a la estructura que el proveedor espere.
El caso más sencillo: el proveedor necesita un recuento de puntos y un ID de miembro, ambos conocidos a partir del contexto.
| code language-jsonata |
|---|
|
Salida:
| code language-json |
|---|
|
rewardContext.rewardValuesiempre es una cadena. Use$number()para convertirlo si su proveedor espera un valor numérico.
kvpCustom para metadatos específicos del proveedorLos proveedores suelen requerir campos como ID de campaña o códigos de sistema de origen específicos para cada desafío ejecutado. Almacénelos en challenge.kvpCustom cuando cree el desafío y luego haga referencia a ellos en la expresión, para que la expresión se pueda reutilizar en todas las campañas.
| code language-jsonata |
|---|
|
También puede usar reward.kvpCustom para constantes fijas para un determinado tipo de recompensa en lugar de por desafío.
Los acumuladores de tareas mantienen un registro de cada evento correspondiente. Use item_list[-1] para acceder al elemento aplicado más recientemente; sus transactionId y timestamp son útiles para las pistas de auditoría y la deduplicación en el lado del proveedor.
| code language-jsonata |
|---|
|
Para los proveedores basados en notificaciones (Slack, SMS, correo electrónico), puede crear una cadena de mensaje directamente mediante el operador de concatenación & de JSONata:
| code language-jsonata |
|---|
|
Salida:
| code language-json |
|---|
|
Ejemplos
Escenario: Una API básica de puntos de fidelidad espera un ID de miembro y una cantidad de puntos.
Definición de recompensa:
| code language-json |
|---|
|
Expresión con formato:
| code language-jsonata |
|---|
|
Carga útil POSTed al proveedor:
| code language-json |
|---|
|
Escenario: El proveedor requiere un registro de asignación estructurado que incluya campos de auditoría, referencias de campaña y descripción de miembro. Los valores específicos de campaña se almacenan en challenge.kvpCustom, por lo que la misma definición de recompensa funciona en todas las campañas sin editar la expresión.
DesafíokvpCustom (establecido al crear el desafío):
| code language-json |
|---|
|
Definición de recompensa:
| code language-json |
|---|
|
Expresión con formato:
| code language-jsonata |
|---|
|
Carga útil POSTed al proveedor:
| code language-json |
|---|
|
Escenario: Un desafío de racha emite un premio hito cada N visitas. La expresión incluye el recuento de hitos y la racha actual para el contexto del lado del proveedor.
Expresión con formato:
| code language-jsonata |
|---|
|
Carga útil publicada en el proveedor (en el segundo hito de visita):
| code language-json |
|---|
|
Cuando
rewardContext.sourcees"milestone", el objetomilestonese rellena concountyreward.rewardValue. Cuando el origen es"task"o"challenge",milestoneesnull.
Referencia de la API
| code language-http |
|---|
|
Todas las solicitudes requieren x-gw-ims-org-id y x-sandbox-name encabezados.
Crear un proveedor:
| code language-http |
|---|
|
| code language-http |
|---|
|
Crear una definición de recompensa:
| code language-http |
|---|
|
Validación de expresión
Se validaron las expresiones rewardJsonata para la sintaxis en el momento de la publicación. Si la expresión no es válida, la API devuelve un error 422 con una descripción del error de análisis.
Para desarrollar y probar una expresión antes de publicarla, use JSONata Exerciser. Pegue el JSON de contexto de recompensa como documento de entrada y la expresión para verificar que la salida coincida con lo que espera el proveedor. En los ejemplos anteriores se muestra un contexto de recompensa representativo para cada tipo de déclencheur (task, milestone, challenge).
Errores comunes
rewardContext.rewardValue se usó como número sin conversión$number(rewardContext.rewardValue)challenge.kvpCustom.someKey devuelve nulokvpCustom en todos los desafíos que utilicen esta definicióntask.accumulators.item_list[-1] es nulotimestamp del contexto en su lugarmilestone cuando el origen es "task" o "challenge"milestone es nulo; la expresión emite o produce campos nulosrewardContext.source antes de acceder a milestone o use milestone solamente en las definiciones adjuntas a las recompensas de hito{ "items": [...] }