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

# Event payloads

> The data object each webhook event type delivers

Every delivery wraps its event in the envelope described in the [Webhooks guide](/guides/webhooks#payload-format). This page lists the `data` object for each event type.

Balance and transfer payloads identify the target with exactly one of `participant_id` or `group_id`, depending on whether the target is a participant or a group. The examples below show the participant form; the group form is identical with `group_id` in place of `participant_id`. For `transfer.completed`, the source field is `source_participant_id` or `source_group_id`.

**`balance.credited` / `balance.debited`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "100.00",
  "bucket": "AVAILABLE",
  "reference_id": "auth_12345",
  "settle": {"held_amount": "80.00", "delta": "20.00"}
}
```

`reference_id` is present when the credit or settle was correlated to a hold. `settle` is present only for settle operations (credit with `reference_id` to AVAILABLE) and contains `held_amount` (total previously held) and `delta` (settle minus held; positive = over-capture, negative = under-capture).

**`balance.expired`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "lot_count": 3
}
```

**`balance.held` / `balance.released`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "100.00"
}
```

**`balance.voided`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "100.00",
  "reference_id": "auth_12345"
}
```

**`transfer.completed`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "source_participant_id": "uuid",
  "asset_id": "uuid",
  "recipients": [
    {
      "participant_id": "uuid",
      "amount": "50.00"
    }
  ]
}
```

<Note>
  The source uses exactly one of `source_participant_id` or `source_group_id`. Each entry in `recipients` contains exactly one of `participant_id` or `group_id`, along with the `amount` transferred to that recipient. Source and recipient types may differ (e.g., a participant can transfer to a group).
</Note>

**`redemption.completed`** (instant amount redemption)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "50.00"
}
```

**`redemption.completed`** (instant catalog item redemption)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "reward_catalog_item_id": "uuid"
}
```

**`redemption.pending`** (amount redemption authorization)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "50.00",
  "reservation_id": "uuid",
  "expires_at": "2026-01-15T11:30:00Z"
}
```

**`redemption.pending`** (catalog item redemption authorization)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "reward_catalog_item_id": "uuid",
  "reservation_id": "uuid",
  "expires_at": "2026-01-15T11:30:00Z"
}
```

`reservation_id` identifies the ledger reservation backing the authorization.
`expires_at` is the server-computed effective capture deadline, which can be
earlier than the requested deadline when a backing lot expires first. Schedule
fulfillment from this delivered value instead of calculating it from the
request. Pending authorization events do not include `status`. The catalog
shape also omits `asset_id` and `amount`.

**`redemption.completed` / `redemption.failed` / `redemption.cancelled`** (pending amount-redemption resolution)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "50.00",
  "status": "FAILED",
  "failure_reason": "provider_rejected"
}
```

**Pending-redemption resolution** (catalog item redemption)

```json theme={null}
{
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "50.00",
  "reward_catalog_item_id": "uuid",
  "status": "CANCELLED"
}
```

`status` is `COMPLETED`, `FAILED`, or `CANCELLED`. `failure_reason` appears
when a fail or cancel request supplies one. Automatic timeout failures use
`failure_reason: "expired"`.

<Warning>
  Successful capture emits `redemption.completed` without a `balance.*` event.
  Reconcile webhook-derived balance mirrors with participant balance and
  statement reads so `HELD` remains accurate.
</Warning>

**`redemption.reversed`**

```json theme={null}
{
  "reversal_id": "uuid",
  "redemption_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "participant_id": "uuid",
  "asset_id": "uuid",
  "amount": "50.00"
}
```

**`reward.status_changed`**

```json theme={null}
{
  "reward_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "previous_status": "ACTIVE",
  "status": "OUT_OF_STOCK"
}
```

`previous_status` is the status before the write. `status` is the status after.
They are always different; a same-status write produces no event.

**`event.reversed`**

One entry per original award line, with the amounts the reversal requested, recovered, and could not recover:

```json theme={null}
{
  "reversal_id": "uuid",
  "event_id": "uuid",
  "organization_id": "uuid",
  "lines": [
    {
      "original_journal_entry_id": "uuid",
      "asset_id": "uuid",
      "requested": "54.25",
      "recovered": "54.25",
      "shortfall": "0"
    }
  ]
}
```

**`participant.created`**

```json theme={null}
{
  "participant_id": "uuid",
  "organization_id": "uuid",
  "external_user_id": "user_123"
}
```

**`participant.tier_changed`**

When the target is a participant:

```json theme={null}
{
  "participant_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "tier": "loyalty",
  "level": "gold"
}
```

When the target is a group:

```json theme={null}
{
  "group_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "tier": "loyalty",
  "level": "gold"
}
```

When the target is a program:

```json theme={null}
{
  "program_id": "uuid",
  "organization_id": "uuid",
  "tier": "loyalty",
  "level": "gold"
}
```

`level` is `null` when a tier is removed (downgrade to base level).

<Note>
  Exactly one of `participant_id`, `group_id`, or `program_id` is present, depending on the target of the tier change. The `SET_TIER` rule action supports cross-targeting via the `target` field, so consumers should not assume this is always a participant.
</Note>

**`program.funded` / `program.burned`**

```json theme={null}
{
  "journal_entry_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "asset_id": "uuid",
  "amount": "1000.00"
}
```

**`event.completed`**

```json theme={null}
{
  "event_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid"
}
```

**`event.failed`**

```json theme={null}
{
  "event_id": "uuid",
  "organization_id": "uuid",
  "program_id": "uuid",
  "error": "description of what went wrong",
  "error_code": "participant_suspended"
}
```

`error_code` is included when the failure has a classified machine-readable code (e.g. `participant_suspended`, `program_inactive`); it is omitted for unclassified failures. The same code is persisted on the event resource, so you can branch on failure type without string-matching `error`. Some early validation failures (e.g. an unparseable payload) omit `program_id`.

<Note>
  For endpoint setup, signature verification, and retry behavior, see the [Webhooks guide](/guides/webhooks).
</Note>
