[Beta privada]{class="badge informative"}

Guía de definición de recompensa reward-definition-guide

Tabla de contenido

Introducción a los retos de fidelización

AVAILABILITY
Esta característica se encuentra actualmente en versión beta privada. Para obtener información detallada acerca del ciclo de lanzamiento y las fases de disponibilidad en Journey Optimizer, consulte ciclo de lanzamiento.

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 JSONatarewardJsonata — 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

Campos del 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 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 se
suspende para todas las definiciones de este proveedor.
url String 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.
Campos de definición de recompensa
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 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á inactiva
y 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 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"
}
Campos de contexto
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.

Carga útil fija simple

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
{
  "memberId":   challenge.profileId,
  "points":     $number(rewardContext.rewardValue),
  "currency":   reward.denomination
}

Salida:

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

rewardContext.rewardValue siempre es una cadena. Use $number() para convertirlo si su proveedor espera un valor numérico.

Usando kvpCustom para metadatos específicos del proveedor

Los 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
{
  "memberId":         challenge.profileId,
  "points":           $number(rewardContext.rewardValue),
  "campaignId":       challenge.kvpCustom.campaignId,
  "transactionSource": "AJO"
}

También puede usar reward.kvpCustom para constantes fijas para un determinado tipo de recompensa en lugar de por desafío.

Usar datos del acumulador de tareas

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
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "transactionId":  task.accumulators.item_list[-1].transactionId,
  "transactionDate": task.accumulators.item_list[-1].timestamp
}
Construcción de un mensaje de texto

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
{
  "text": "You just earned " & rewardContext.rewardValue & " " & reward.denomination & "!"
}

Salida:

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

Ejemplos

Ejemplo 1 — Proveedor de puntos simple

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
{
  "name":         "Standard Points",
  "denomination": "Points",
  "desc":         "Award loyalty points",
  "enabled":      true,
  "rewardJsonata": "{\"memberId\": challenge.profileId, \"pointQuantity\": $number(rewardContext.rewardValue), \"denomination\": reward.denomination}"
}

Expresión con formato:

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

Carga útil POSTed al proveedor:

code language-json
{
  "memberId":      "ADB-0000030",
  "pointQuantity": 50,
  "denomination":  "Points"
}
Ejemplo 2: Carga útil del proveedor con metadatos de campaña

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
{
  "parentCampaignId": "CAMP-2026-Q1",
  "productName":      "Loyalty Program"
}

Definición de recompensa:

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

Expresión con formato:

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

Carga útil POSTed al proveedor:

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
    }
  ]
}
Ejemplo 3 — Recompensa de hito

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
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "milestoneCount": milestone.count,
  "currentStreak":  task.schedule.currentStreak,
  "denomination":   reward.denomination,
  "source":         rewardContext.source
}

Carga útil publicada en el proveedor (en el segundo hito de visita):

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

Cuando rewardContext.source es "milestone", el objeto milestone se rellena con count y reward.rewardValue. Cuando el origen es "task" o "challenge", milestone es null.

Referencia de la API

Proveedores de recompensas
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}

Todas las solicitudes requieren x-gw-ims-org-id y x-sandbox-name encabezados.

Crear un proveedor:

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"
  }
}
Definiciones de recompensa
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}

Crear una definición de recompensa:

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

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

Error
Efecto
Corregir
rewardContext.rewardValue se usó como número sin conversión
El tipo no coincide si el proveedor valida el campo como numérico
Ajustar con $number(rewardContext.rewardValue)
challenge.kvpCustom.someKey devuelve nulo
La clave no se establece en el desafío en el momento de la creación
Asegúrese de que la clave esté presente en kvpCustom en todos los desafíos que utilicen esta definición
task.accumulators.item_list[-1] es nulo
No se aplicó ningún artículo antes de la recompensa emitida (evento sin compra)
Protéjase con un condicional o use timestamp del contexto en su lugar
Se accedió a milestone cuando el origen es "task" o "challenge"
milestone es nulo; la expresión emite o produce campos nulos
Compruebe rewardContext.source antes de acceder a milestone o use milestone solamente en las definiciones adjuntas a las recompensas de hito
La expresión devuelve una matriz en lugar de un objeto
El proveedor recibe una estructura de carga útil inesperada
Agrupar expresiones que devuelven matrices en un objeto externo: { "items": [...] }
recommendation-more-help
journey-optimizer-help