# Rewards

> Who pays for what, voucher codes, and reward statuses.

Source: https://docs.onari.xyz/docs/concepts/rewards

Onari decides **who wins**. Paying is either done by Onari (voucher codes) or by your server, when Onari tells it to.

| Reward | Who delivers it | What your server does |
|---|---|---|
| **Voucher code** | Onari: one of your uploaded codes is given to the winner and shown in their Rewards Hub. | Nothing required. The code is also in the `reward.issued` webhook if you want to send it by SMS or email. |
| **Cashback** | You | Credit the player's wallet or account when `reward.issued` arrives. |
| **Airtime or data** | You | Send it through your provider. |
| **Perk** (free delivery, fee waiver…) | You | Apply the perk to the player's account. |

## Voucher codes

Your team uploads codes in **Rewards → Voucher codes** (paste or CSV). Each winner gets one unused code. If the codes run out, the win is recorded as **failed** with reason `no_codes_left`; add more codes and resend it from the dashboard. The winner never loses the win.

## Statuses

| Status | Meaning |
|---|---|
| `issued` | Won. If it's yours to pay, pay it. |
| `delivered` | Paid or handed over. Voucher codes are `delivered` as soon as they're assigned. |
| `failed` | Couldn't be given yet (for example, no voucher codes left). |

Mark cash, airtime and perk rewards as paid in **Rewards → Payouts** so your team can see what's outstanding.

## Paying exactly once

Each reward has an ID, and `reward.issued` carries `idempotency_key: "rw_<reward id>"`. Store it with the payment on your side and check it before paying, so a webhook retry never pays twice. See [Webhooks](/docs/webhooks).
