> ## Documentation Index
> Fetch the complete documentation index at: https://developers.bonifiq.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks - Recompensas

> Payloads de webhook para resgates de recompensas e seus cancelamentos

Este documento descreve os payloads de webhook relacionados a resgates de recompensas.

Os tópicos **`Reward_Redeemed` (`30`)** e **`Reward_Cancelled` (`31`)** acompanham o ciclo de vida de um resgate. No painel, eles aparecem como **Recompensa resgatada** e **Recompensa cancelada**. Os dois compartilham a mesma estrutura base, e o cancelamento acrescenta os campos do cancelamento.

Use estes tópicos para sincronizar resgates com sua integração. Eles são independentes de `Communication_RedeemPoints` e `Communication_RewardCustomRedeemNotification`, que continuam seguindo as regras de comunicação e só são enviados quando a comunicação de resgate é disparada.

## Resgate de recompensa

O tópico **`Reward_Redeemed` (`30`)** é enviado quando o cliente troca pontos por uma recompensa.

### Quando o evento é gerado

O evento é gerado em todos os resgates, para qualquer tipo de recompensa (cupom, cashback ou recompensa customizada) e qualquer origem: página do programa, widget, checkout, API e PDV. A origem vem no campo [`RedeemOrigin`](#enums).

Cada resgate gera no máximo um evento por assinatura. O evento é enviado mesmo que o resgate já tenha sido cancelado quando a entrega acontece; nesse caso, o cancelamento chega separadamente em `Reward_Cancelled`.

<Note>
  No checkout, cada atualização do carrinho pode cancelar o resgate anterior e criar um novo. Nesses casos, você recebe um `Reward_Redeemed` para cada resgate e um `Reward_Cancelled` para cada resgate substituído. Use `RewardId` para cruzar os dois eventos.
</Note>

### Exemplo

Exemplo completo com o envelope padrão, em um resgate de cashback feito no checkout:

```json theme={null}
{
  "Uuid": "8d0f6a3c-2e4b-4f1a-9c7d-5b3e1a9f0c62",
  "Timestamp": "2026-10-05T14:07:00.418263",
  "Topic": 30,
  "TopicName": "Reward_Redeemed",
  "Payload": {
    "RewardId": 4321,
    "RewardConfigurationId": 12,
    "RewardType": 3,
    "CouponCode": null,
    "ExternalCode": "checkout-5f2c9a7e1b",
    "PointId": 98765,
    "Points": 500,
    "CashValue": 5.00,
    "RedeemDate": "2026-10-05T14:05:00.127941",
    "RedeemOrigin": 3,
    "Customer": {
      "Email": "cliente@exemplo.com",
      "Id": "id_original_cliente_123",
      "Name": "João Silva",
      "Phone": "+5511999998888",
      "Document": "12345678900",
      "BirthdayDate": "1990-05-20T00:00:00",
      "PointsBalance": 1000,
      "Rfm": null
    },
    "PointsBalance": {
      "PointsBalance": 1000,
      "CashbackBalance": 10.00
    }
  }
}
```

### Campos do payload

| Campo | Tipo | Descrição |
| - | - | - |
| `RewardId` | integer | ID interno do resgate na BonifiQ. É o mesmo em `Reward_Redeemed` e `Reward_Cancelled`. |
| `RewardConfigurationId` | integer | ID da recompensa configurada no painel. |
| `RewardType` | integer | Tipo da recompensa. Veja [`RewardType`](#enums). |
| `CouponCode` | string ou null | Código do cupom gerado no resgate; `null` quando o resgate não gera cupom. |
| `ExternalCode` | string | Código externo do resgate, usado para vinculá-lo a um pedido. **Não é único:** no checkout, todos os resgates do mesmo carrinho compartilham o valor `checkout-<id do carrinho>`; nos demais resgates é um identificador gerado. Use `RewardId` para identificar o resgate. |
| `PointId` | integer | ID da transação de pontos do resgate. É o mesmo `PointId` dos [tópicos de pontos](/webhooks/03-webhook-pontos) quando houver evento correspondente; se o resgate for cancelado logo depois de feito, os tópicos de pontos podem não enviar evento para essa transação. |
| `Points` | integer | Pontos gastos no resgate. Pode ser `0` em recompensas sem custo em pontos. |
| `CashValue` | number ou null | Valor monetário do resgate (cashback ou valor do cupom), quando houver. |
| `RedeemDate` | string (date-time) | Data do resgate, em UTC. Veja o [formato das datas](#formato-das-datas). |
| `RedeemOrigin` | integer ou null | Onde o resgate foi feito. Veja [`RedeemOrigin`](#enums). |
| `Customer` | object | [Objeto Cliente](/webhooks/01-introducao#objetos-de-dados-comuns). |
| `PointsBalance` | object | [Objeto Saldo de Pontos](/webhooks/01-introducao#objetos-de-dados-comuns). |

***

## Recompensa cancelada

O tópico **`Reward_Cancelled` (`31`)** é enviado quando um resgate de recompensa é cancelado e os pontos voltam para o cliente.

### Quando o evento é gerado

O evento é gerado nos cancelamentos feitos pelo fluxo padrão de cancelamento de resgates, incluindo:

* cancelamento pela API e pelo PDV;
* remoção do resgate pelo cliente no checkout;
* cancelamentos automáticos do checkout: atualização do carrinho, carrinho abandonado e chave de segurança ausente ou inválida;
* cancelamento automático do resgate quando o pedido que o utilizou é cancelado.

A origem de cada cancelamento vem no campo [`CancellationType`](#enums). Um resgate só pode ser cancelado uma vez, então cada resgate gera no máximo um evento de cancelamento por assinatura.

<Note>
  Os cancelamentos automáticos do checkout são frequentes: a cada atualização do carrinho, o resgate anterior pode ser cancelado e substituído por um novo. Use `CancellationType` para filtrar as origens relevantes para sua integração.
</Note>

### Exemplo

Payload do cancelamento do resgate do exemplo anterior, feito pela API (sem o envelope, que segue o mesmo formato com `Topic` `31` e `TopicName` `"Reward_Cancelled"`):

```json theme={null}
{
  "RewardId": 4321,
  "RewardConfigurationId": 12,
  "RewardType": 3,
  "CouponCode": null,
  "ExternalCode": "checkout-5f2c9a7e1b",
  "PointId": 98765,
  "Points": 500,
  "CashValue": 5.00,
  "RedeemDate": "2026-10-05T14:05:00.127941",
  "RedeemOrigin": 3,
  "Customer": {
    "Email": "cliente@exemplo.com",
    "Id": "id_original_cliente_123",
    "Name": "João Silva",
    "Phone": "+5511999998888",
    "Document": "12345678900",
    "BirthdayDate": "1990-05-20T00:00:00",
    "PointsBalance": 1500,
    "Rfm": null
  },
  "PointsBalance": {
    "PointsBalance": 1500,
    "CashbackBalance": 15.00
  },
  "CancelledDate": "2026-10-05T14:30:00.563107",
  "CancellationType": 3
}
```

### Campos do payload

Todos os campos de [`Reward_Redeemed`](#campos-do-payload), com estas diferenças:

| Campo | Tipo | Descrição |
| - | - | - |
| `Points` | integer | Pontos do resgate devolvidos ao cliente, já descontados os reembolsos parciais que o resgate tinha recebido. Pode ser `0`. |
| `PointsBalance` | object | [Objeto Saldo de Pontos](/webhooks/01-introducao#objetos-de-dados-comuns), já com os pontos devolvidos. |
| `CancelledDate` | string (date-time) | Data do cancelamento, em UTC. Veja o [formato das datas](#formato-das-datas). |
| `CancellationType` | integer ou null | Origem do cancelamento. Veja [`CancellationType`](#enums). |

***

## Enums

<Tabs>
  <Tab title="RewardType">
    Indica o tipo da recompensa resgatada.

    | Valor | Nome | Descrição |
    | - | - | - |
    | `0` | PercentDiscountCoupon | Cupom de desconto percentual |
    | `1` | ValueDiscountCoupon | Cupom de desconto em valor |
    | `2` | FreightDiscountCoupon | Cupom de desconto no frete |
    | `3` | PointToCashback | Troca de pontos por cashback |
    | `4` | Customized | Recompensa customizada |
  </Tab>

  <Tab title="RedeemOrigin">
    Indica onde o resgate foi feito.

    | Valor | Nome | Descrição |
    | - | - | - |
    | `0` | LandingPage | Página do programa de fidelidade |
    | `1` | Widget | Widget da loja |
    | `2` | Copilot | Copilot |
    | `3` | Checkout | Checkout da loja |
    | `4` | API | API |
    | `5` | PDV | Fidelidade no caixa (PDV) |
    | `null` | — | Origem não informada pelo canal que fez o resgate; pode acontecer inclusive no checkout |
  </Tab>

  <Tab title="CancellationType">
    Indica a origem do cancelamento.

    | Valor | Nome | Descrição |
    | - | - | - |
    | `0` | Refresh | Cancelamento automático do checkout, em geral porque o carrinho mudou e o resgate foi substituído. Algumas plataformas também usam este valor na rotina de carrinho abandonado |
    | `1` | Removed | Cliente removeu o resgate no checkout |
    | `2` | AbandonedCart | Rotina de carrinho abandonado |
    | `3` | API | Cancelamento pela API |
    | `4` | PDV | Cancelamento pelo PDV |
    | `5` | MissingSecurityKey | Cancelamento automático no checkout por chave de segurança ausente ou inválida |
    | `null` | — | Origem não informada, como no cancelamento automático quando o pedido é cancelado ou em rotinas internas de correção |
  </Tab>
</Tabs>

***

## Entrega

<Note>
  Apenas assinaturas ativas com o tópico selecionado no momento do evento recebem a notificação. Ativar a assinatura ou adicionar o tópico não recupera resgates ou cancelamentos anteriores. Rotinas internas de correção que usam o fluxo padrão de resgate e cancelamento também geram estes eventos, em geral com `CancellationType` `null`. Ajustes feitos diretamente no resgate, sem passar por esse fluxo (algumas sincronizações específicas de plataforma ou correções no banco), não geram eventos.
</Note>

As entregas são assíncronas, podem levar alguns minutos e podem se repetir.

1. Use o `Uuid` do envelope para deduplicar as tentativas da mesma entrega. Ele permanece igual nas retentativas; assinaturas diferentes têm seus próprios `Uuid`.
2. Use `TopicName` + `RewardId` como chave de idempotência de negócio: cada resgate gera no máximo um evento de cada tópico por assinatura. Use `RewardId` para cruzar `Reward_Redeemed` com `Reward_Cancelled` e `PointId` para cruzar com os tópicos de pontos.
3. Não há garantia de ordem entre os tópicos. No checkout, quando o resgate é cancelado logo depois de feito, o `Reward_Cancelled` pode chegar antes do `Reward_Redeemed` do mesmo resgate. Trate o cancelamento como estado final: se o `Reward_Redeemed` chegar depois, não reative o resgate.

Os dados do payload são lidos no momento do envio. `Customer` e `PointsBalance` podem refletir movimentações de pontos posteriores ao evento, principalmente em retentativas. Em algumas plataformas, rotinas de reconciliação também podem ajustar `CashValue` e `Points` do resgate depois do evento.

### Formato das datas

`RedeemDate`, `CancelledDate` e o `Timestamp` do envelope estão em UTC, mas são enviados **sem designador de fuso** e com até seis casas decimais nos segundos, por exemplo `2026-10-05T14:05:00.127941`. Trate esses valores como UTC: em JavaScript, por exemplo, `new Date("2026-10-05T14:05:00.127941")` interpreta a data como hora local.

Estes tópicos usam a [política de entrega existente](/webhooks/01-introducao#garantias-de-entrega), com os headers, método, URL e corpo configurados na assinatura.

<Warning>
  Prefira o envelope padrão para ter acesso ao `Uuid`. Um corpo personalizado recebe os campos deste payload, como `RewardId` e `Customer.Id`, mas não recebe automaticamente os campos do envelope. Consulte a [configuração do corpo personalizado](/webhooks/00-configuracao#campos-do-formulário).
</Warning>

***

## Tópicos Disponíveis

| Tópico | Descrição |
| - | - |
| `Reward_Redeemed` | Recompensa resgatada (código `30`) |
| `Reward_Cancelled` | Recompensa cancelada (código `31`) |

***

<Info>
  Documentação atualizada em Outubro de 2026.
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.