> ## Documentation Index
> Fetch the complete documentation index at: https://docs.masivo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate rewards redemption

> Learn how to preview & validate rewards redemptions

<Note>
  Check the complete list of parameters and responses of the [`PUT
      redeem/preview`](/api-reference/events/redeem/preview/put) endpoint to preview
  or validate rewards redemptions.
</Note>

## Overview

When you want to emit a *purchase event* that contains rewards redemptions, you may want 2 things before emitting the event:

1. **Preview the rewards redemptions**: This allows your customers to be sure what they are going to redeem before they actually redeem it.
2. **Validate the rewards redemptions**: This allows you to check if the rewards redemptions are valid and can be redeemed.

### Why do we need to check if a redemption is valid?

Every type of reward have different rules to follow in order to be redeemed.

**POINTS**: Can be redeemed at any level, this is the reward type that is most flexible.

**DISCOUNT**: Discounts when created are configured to work on a specific entity, like a product, the shipping cost, or the order value. When redeeming a discount, you need to set the discount at the same entity that was configured.

**PRODUCT**: Either ADD or REPLACE product rewards must only be redeemed at the order level. This is because adding a product that doesn't exist or replacing a product for another one, you wouldn't have a place to set the rewards to be redeemed.

**GIFT CARD**: Gift cards are redeemed using only the redeem gift card endpoints. Redeeming a gift card in a purchase event will not work.

Additionally, each reward may have some conditions configured to be met in order to be redeemed. For example, a discount may have a minimum order value to be redeemed.

## Preview rewards redemptions

To preview rewards redemptions, you need to send a `PUT` request to the [`redeem/preview`](/api-reference/events/redeem/preview/put) endpoint.

The endpoint will send back the exact order you originally sent, but with an additional keyword redemptions\_result at each level where a `redeem` array was found.

The endpoint doesn't want to force you how to present the data to the customer, it just provide the data you need to build whatever experience you want to show.

### Example Order sent

Let's pretend we want to preview the rewards redemptions for the following order:

```json theme={null}
{
  "order": {
    "products": [
      {
        "sku": "123",
        "amount": 1,
        "value": 10,
        // Rewards to be redeemed at the product level
        "redeem": [
          {
            "reward_id": "<points-id>",
            "amount": 6 // Assume a conversion factor of 1
          }
        ]
      }
    ],
    "shipping": {
      "value": 2
    },
    "value": 12
  }
}
```

### Example Order received

The response will be the same order you sent, but with the rewards redemptions previewed:

```json theme={null}
{
  "order": {
    "products": [
      {
        "sku": "123",
        "amount": 1,
        "value": 10,
        "redeem": [
          {
            "reward_id": "<points-id>",
            "amount": 6
          }
        ],
        "redemptions_result": {
          "redeemed": [
            {
              "id": "<points-id>",
              "action": "UPDATE",
              "amount": 6,
              "reward": {
                /* reward data */
              }
            }
          ],
          "value": 4,
          "amount": 1,
          "discount_value": 6,
          "discount_percent": 0.6,
          "action": "UPDATE"
        }
      }
    ],
    "shipping": {
      "value": 2
    },
    "value": 12,
    "redemptions_result": {
      "redeemed": [],
      "value": 6,
      "amount": 1,
      "discount_value": 6,
      "discount_percent": 0.5,
      "action": "UPDATE"
    }
  }
}
```

Several things happened in the response:

1. The `redemptions_result` object was to the product that redeemed 6 points.
2. This new object contains the discounted value of the product `value`, how much was discounted `discount_value`, the percentage of the discount `discount_percent`. This values can be used to show the customer how much they are saving.
3. It also contains an `action` field that tells you what to do with the affected entity:
   * `UPDATE`: The entity was updated, display these values instead.
   * `READ`: The entity has been updated before, but the last redeem didn't change anything.
   * `DELETE`: Then entity was removed, don't display this item in the order.
   * `CREATE`: The entity is new and must be display along the other products in the order.
4. The `redeemed` array contains the rewards that were redeemed. This array will contain the rewards that were redeemed and the action that was taken.
5. Even though we redeemed a reward at the product level, a redemption\_result was created at the order level as well. This is because the order level was affected by the redemption.

### Example Order with an error

Some rewards may have conditions that need to be met in order to be redeemed. If the conditions are not met, the rewards will not be redeemed. Take into consideration that the response will end with a status of 200. You will need to display the error to the customer.

```json theme={null}
{
  "order": {
    "products": [
      {
        "sku": "123",
        "amount": 1,
        "value": 10,
        "redeem": [
          {
            "reward_id": "<discount-id>",
            "amount": 6
          }
        ],
        "redemptions_result": {
          "redeemed": [
            {
              "id": "<discount-id>",
              "action": "READ",
              "amount": 1,
              "reward": {
                /* reward data */
              },
              "error": "Cannot redeem a shipping discount on a product"
            }
          ],
          "value": 3,
          "amount": 1,
          "discount_value": 0,
          "discount_percent": 0,
          "action": "READ"
        }
      }
    ],
    "shipping": {
      "value": 2
    },
    "value": 12
  }
}
```

In this case, the discount was not redeemed because it was a shipping discount and it was redeemed at the product level.
A new field `error` was added to the redeemed object. This error can either be shown to the customer or used to debug your implementation.

### Re-validating an order

Many things may happen that will force you to update an order. For example: adding/removing products, applying/removing a reward, updating an item amount, changing the delivery address, etc. After each of these situations, you will need to re-validate the order.

When revalidating the order you **must keep a copy of your original products and values**. Do not replace them with the 'redemptions\_result' object. This data should only be used to help your customers preview the rewards redemptions. Use the action field to know what to do with the entity.

If you are re-validating an order, it is super important to also bring with you the 'redemptions\_result' object of each entity. Masivo will use these objects to know what rewards to redeem next, which rewards were already redeemed, and which rewards were removed.

## Validate rewards redemptions

The same endpoint can be repurpose to validate an order. Call this endpoint in your backend and use the field `order.redemptions_result.value` to compare if what you are going to charge the customer matches.

If the order values don't match, the order may have been tampered with. You should not emit the event.

<Tip>
  Masivo also checks if all conditions match for a redemption when an event is
  emitted. If the conditions don't match, or whether the customer has
  insufficient funds, the event will be rejected.
</Tip>
