> ## Documentation Index
> Fetch the complete documentation index at: https://rain-sandbox-trial.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Raindrops Rewards

> Track Raindrops balance requests and the travel redemption lifecycle so you can keep user point balances in sync with your platform.

Rain sends Raindrops webhooks to notify your systems about balance requests
and redemption events. Use these webhooks to integrate Raindrops rewards into
your platform, track redemptions, and manage user point balances.

<Check>
  **Rewards webhooks:**

  Rewards webhooks cover both the Rain-Managed travel authorization flow and
  Partner-Managed balance, completion, and refund events.
</Check>

The following events are available:

| Event                                                             | Description                                                  |
| ----------------------------------------------------------------- | ------------------------------------------------------------ |
| [`raindrop_balance.requested`](#raindrop_balance-requested)       | Rain needs a user's current Raindrops balance.               |
| [`raindrop_redemption.created`](#raindrop_redemption-created)     | A Rain-Managed redemption needs on-chain burn authorization. |
| [`raindrop_redemption.completed`](#raindrop_redemption-completed) | A travel redemption is marked completed.                     |
| [`raindrop_redemption.refunded`](#raindrop_redemption-refunded)   | A travel redemption is refunded.                             |

## `raindrop_balance.requested`

<Warning>
  **Synchronous webhook:**

  Your endpoint must respond within 1500ms with the user's available balance.
</Warning>

Rain sends this webhook to `PARTNER_ONCHAIN` tenants when it needs a user's
current Raindrops balance. Your endpoint must return the user's
`availableBalance` within 1500ms. `PARTNER_OFFCHAIN` tenants do not receive
this webhook because Rain manages their balance ledger.

Rain signs the raw JSON request body with your webhook signing key and sends
the hex HMAC-SHA256 digest in the `Signature` header. Verify this signature
before you return a balance.

```json Request theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "raindrop_balance",
    "action": "requested",
    "version": "1.0.0",
    "body": {
        "id": "user_def456"
    }
}
```

| Field      | Type     | Description                            |
| ---------- | -------- | -------------------------------------- |
| `id`       | `string` | Webhook ID                             |
| `resource` | `string` | Always `raindrop_balance`              |
| `action`   | `string` | Always `requested`                     |
| `version`  | `string` | The webhook version                    |
| `body.id`  | `string` | The user ID to look up the balance for |

### Response

Return a JSON response with the user's available balance as a string.

```json Response theme={null}
{
    "availableBalance": "5000"
}
```

| Field              | Type     | Description                                                                                        |
| ------------------ | -------- | -------------------------------------------------------------------------------------------------- |
| `availableBalance` | `string` | The user's available Raindrops balance in whole reward points, as a string (for example, `"5000"`) |

If you return a non-2xx status, malformed JSON, or no response within 1500ms,
Rain treats the balance as unavailable and the calling travel-balance or
travel-redemption request receives `503 Service Unavailable`.

## `raindrop_redemption.created`

This webhook is sent for Rain-Managed redemptions when Rain reserves the
redemption and needs your application to prompt the user for on-chain burn
authorization, such as when the travel portal reserves a booking. The `amount`
is in native 18-decimal TenantToken units. Partner-Managed travel redemptions
skip this step and do not receive `created`.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "raindrop_redemption",
    "action": "created",
    "version": "1.1.0",
    "body": {
        "id": "redemption_abc123",
        "userId": "user_def456",
        "amount": "1000000000000000000000",
        "amountUnit": "wei"
    },
    "eventReceivedAt": "2026-03-17T02:30:00.000Z"
}
```

| Field             | Type                | Description                                                            |
| ----------------- | ------------------- | ---------------------------------------------------------------------- |
| `id`              | `string`            | Webhook ID                                                             |
| `resource`        | `string`            | Always `raindrop_redemption`                                           |
| `action`          | `string`            | Always `created`                                                       |
| `version`         | `string`            | The webhook version                                                    |
| `body.id`         | `string`            | The redemption ID                                                      |
| `body.userId`     | `string`            | The ID of the user redeeming points                                    |
| `body.amount`     | `string`            | The TenantToken amount to burn in native 18-decimal units              |
| `body.amountUnit` | `string`            | The unit of `amount`. Always `wei`. Requires version `1.1.0` or later. |
| `eventReceivedAt` | `string` (optional) | ISO 8601 timestamp                                                     |

## `raindrop_redemption.completed`

This webhook is sent to Partner-Managed tenants when a travel redemption is
marked completed. For `PARTNER_ONCHAIN`, use this event to burn the user's
points in your system. For `PARTNER_OFFCHAIN`, Rain has already debited the
off-chain balance and the event is informational.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "raindrop_redemption",
    "action": "completed",
    "version": "1.0.0",
    "body": {
        "id": "redemption_abc123",
        "userId": "user_def456",
        "type": "TRAVEL_PORTAL",
        "raindropAmount": "1000",
        "bookingId": "booking_xyz789"
    },
    "eventReceivedAt": "2026-06-08T14:30:00.000Z"
}
```

| Field                 | Type                | Description                                                                              |
| --------------------- | ------------------- | ---------------------------------------------------------------------------------------- |
| `id`                  | `string`            | Webhook ID                                                                               |
| `resource`            | `string`            | Always `raindrop_redemption`                                                             |
| `action`              | `string`            | Always `completed`                                                                       |
| `version`             | `string`            | The webhook version                                                                      |
| `body.id`             | `string`            | The redemption ID                                                                        |
| `body.userId`         | `string`            | The ID of the user who redeemed points                                                   |
| `body.type`           | `string`            | The redemption type. Currently `TRAVEL_PORTAL`                                           |
| `body.raindropAmount` | `string`            | The amount of points redeemed, in whole reward points (not 18-decimal TenantToken units) |
| `body.bookingId`      | `string` (optional) | The travel booking ID. Only present for `TRAVEL_PORTAL` redemptions                      |
| `eventReceivedAt`     | `string` (optional) | ISO 8601 timestamp                                                                       |

## `raindrop_redemption.refunded`

This webhook is sent when a travel portal redemption is refunded. For
`PARTNER_ONCHAIN`, update the user's balance in your own system. For
`PARTNER_OFFCHAIN` and Rain-Managed programs, Rain handles the refund balance
update.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "raindrop_redemption",
    "action": "refunded",
    "version": "1.0.0",
    "body": {
        "id": "redemption_abc123",
        "userId": "user_def456"
    },
    "eventReceivedAt": "2026-06-08T14:30:00.000Z"
}
```

| Field             | Type                | Description                                      |
| ----------------- | ------------------- | ------------------------------------------------ |
| `id`              | `string`            | Webhook ID                                       |
| `resource`        | `string`            | Always `raindrop_redemption`                     |
| `action`          | `string`            | Always `refunded`                                |
| `version`         | `string`            | The webhook version                              |
| `body.id`         | `string`            | The redemption ID                                |
| `body.userId`     | `string`            | The ID of the user whose redemption was refunded |
| `eventReceivedAt` | `string` (optional) | ISO 8601 timestamp                               |

## What's next

<Card title="How webhooks work" icon="webhook" href="/docs/webhooks">
  Browse every other event category from the hub.
</Card>
