> ## 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.

# Custom Redemptions

> Record or process a partner-initiated redemption for any reward you define.

Use custom redemptions to record or process a partner-initiated redemption that you procure and fulfill yourself. You supply the cardholder, the point amount, and a reason, and Rain handles the redemption recording according to your program's points mode.

Custom redemptions are available for **Rain-Managed** and **Partner-Managed Offchain** programs. Partner-Managed Onchain programs should not use this endpoint, but may orchestrate token burns for custom redemptions directly with their users.

How a custom redemption settles depends on your points mode:
**Rain-Managed:** The points live onchain, so Rain reserves them as a pending `CUSTOM` redemption and fires the `raindrop_redemption.created` webhook so you can prompt the cardholder to authorize the burn. The redemption then settles onchain through the same withdrawal-signature and burn-event flow as travel redemptions, moving from `PENDING` to `PROCESSING` when the burn signature is issued and to `COMPLETED` once the onchain burn confirms. You fulfill the reward in your own system.

**Partner-Managed Offchain:** Rain checks the cardholder's offchain points balance, debits the points, and records a completed `CUSTOM` redemption. There is no onchain burn and no webhook. You own fulfillment, funding, and any reversal logic outside Rain's rewards redemption flow.

## How It Works

### Partner-Managed Offchain

<Steps>
  <Step title="Cardholder requests a reward">
    The cardholder requests a custom reward in your app.
  </Step>

  <Step title="Call the endpoint">
    Call `POST /issuing/raindrops/custom-redemption` with the user, the point amount, and a reason.
  </Step>

  <Step title="Rain records the redemption">
    Rain checks the cardholder's offchain points balance, debits the points, and records a completed `CUSTOM` redemption.
  </Step>

  <Step title="You fulfill the reward">
    Fulfill the reward in your own system.
  </Step>
</Steps>

### Rain-Managed

<Steps>
  <Step title="Cardholder requests a reward">
    The cardholder requests a custom reward in your app.
  </Step>

  <Step title="Call the endpoint">
    Call `POST /issuing/raindrops/custom-redemption` with the user, the point amount, and a reason.
  </Step>

  <Step title="Rain reserves the points">
    Rain checks the cardholder's available balance, reserves a `PENDING` `CUSTOM` redemption, and fires the `raindrop_redemption.created` webhook.
  </Step>

  <Step title="Cardholder authorizes the burn">
    Prompt the cardholder to authorize the burn. The redemption moves to `PROCESSING` when the burn signature is issued and to `COMPLETED` once the onchain burn confirms.
  </Step>

  <Step title="You fulfill the reward">
    Fulfill the reward in your own system.
  </Step>
</Steps>

### Rain-Managed

<Steps>
  <Step title="Cardholder requests a reward">
    The cardholder requests a custom reward in your app.
  </Step>

  <Step title="Call the endpoint">
    Call `POST /issuing/raindrops/custom-redemption` with the user, the point amount, and a reason.
  </Step>

  <Step title="Rain reserves the points">
    Rain checks the cardholder's available balance, reserves a `PENDING` `CUSTOM` redemption, and fires the `raindrop_redemption.created` webhook.
  </Step>

  <Step title="Cardholder signs the burn">
    Prompt the cardholder to sign the burn transaction, similarly to how travel portal redemptions are actioned. The redemption moves to `PROCESSING` when the burn signature is issued and to `COMPLETED` once the onchain burn confirms.
  </Step>

  <Step title="You fulfill the reward">
    Fulfill the reward in your own system.
  </Step>
</Steps>

### Partner-Managed Offchain

<Steps>
  <Step title="Cardholder requests a reward">
    The cardholder requests a custom reward in your app.
  </Step>

  <Step title="Call the endpoint">
    Call `POST /issuing/raindrops/custom-redemption` with the user, the point amount, and a reason.
  </Step>

  <Step title="Rain records the redemption">
    Rain checks the cardholder's offchain points balance, debits the points, and records a completed `CUSTOM` redemption.
  </Step>

  <Step title="You fulfill the reward">
    Fulfill the reward in your own system.
  </Step>
</Steps>

## Request

Send the user, the point amount as a positive integer string, and a reason. Include an `idempotency-key` header so that retries replay the same response.

```bash theme={null}
curl -X POST https://api.rain.xyz/v1/issuing/raindrops/custom-redemption \
  -H "Api-Key: YOUR_API_KEY" \
  -H "idempotency-key: <UNIQUE_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "1f2e3d4c-5b6a-7980-1234-567890abcdef",
    "raindropAmount": "100",
    "reason": "goodwill credit"
  }'
```

| Field            | Type          | Description                                                                       |
| ---------------- | ------------- | --------------------------------------------------------------------------------- |
| `userId`         | string (UUID) | The cardholder redeeming points.                                                  |
| `raindropAmount` | string        | The number of points to redeem, as a positive integer string.                     |
| `reason`         | string        | Why the redemption is being made, 1–255 characters. Recorded with the redemption. |

## Response

A successful request returns `201`. The `status` reflects how the redemption settles for your points mode: Partner-Managed Offchain redemptions are recorded as `COMPLETED`, while Rain-Managed redemptions return `PENDING` and settle onchain.

```json theme={null}
{
  "redemptionId": "9a8b7c6d-5e4f-3210-fedc-ba0987654321",
  "redemptionType": "CUSTOM",
  "raindropAmount": "100",
  "status": "PENDING"
}
```

<Info>
  Reusing the same `idempotency-key` and body replays the cached `201` response, so a retried request never double-debits the balance. The key is limited to 64 characters.
</Info>

## Errors

| Status | Meaning                                                                                                                                          |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | Invalid request, a missing or invalid `idempotency-key`, or insufficient points balance.                                                         |
| `403`  | Raindrops are not enabled for this tenant.                                                                                                       |
| `404`  | The user was not found in this tenant.                                                                                                           |
| `405`  | The tenant's points mode does not support custom redemptions (Partner-Managed Onchain).                                                          |
| `409`  | Another offchain redemption is already in progress for this user.                                                                                |
| `503`  | For Rain-Managed programs, the burn-request webhook could not be sent. The reservation is released and no points are debited. Retry the request. |

## Billing Impact

Custom redemptions do not create a charge at redemption time. Partner-Managed Offchain redemptions carry no charge from Rain and are excluded from charge reconciliation. You own any funding or accounting for the reward you fulfill.
