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

# Webhook Events

> Complete reference for all webhook event types and their payloads.

# Webhook Events

Events use dot-notation grouping: `{object}.{action}`. All events share the same [envelope structure](/webhooks/overview#envelope-structure) — the `data` field contains the event-specific object documented below.

## Event Taxonomy

### payment.\*

| Event               | When it fires                                                            |
| ------------------- | ------------------------------------------------------------------------ |
| `payment.succeeded` | A charge completed successfully (one-time, subscription, or installment) |
| `payment.failed`    | A charge attempt failed                                                  |
| `payment.refunded`  | A full or partial refund was processed                                   |
| `payment.disputed`  | A customer opened a chargeback/dispute                                   |

### subscription.\*

| Event                         | When it fires                                             |
| ----------------------------- | --------------------------------------------------------- |
| `subscription.created`        | A new subscription was initiated                          |
| `subscription.renewed`        | A recurring charge succeeded                              |
| `subscription.payment_failed` | A renewal charge failed                                   |
| `subscription.cancelled`      | Subscription was cancelled (immediately or at period end) |
| `subscription.expired`        | Period ended without renewal                              |
| `subscription.trial_started`  | Trial period began                                        |
| `subscription.trial_ending`   | 3 days before trial ends (grace notification)             |
| `subscription.trial_ended`    | Trial period ended (converted or expired)                 |

### wallet.\*

| Event             | When it fires                                                   |
| ----------------- | --------------------------------------------------------------- |
| `wallet.credited` | Merchant wallet was credited (after a successful sale)          |
| `wallet.debited`  | Wallet was debited (refund issued, dispute hold placed, payout) |

### settlement.\*

| Event                   | When it fires                                    |
| ----------------------- | ------------------------------------------------ |
| `settlement.initiated`  | Payout/withdrawal was requested                  |
| `settlement.processing` | Gateway confirmed it is processing               |
| `settlement.completed`  | Funds confirmed delivered to the merchant's bank |
| `settlement.failed`     | Payout failed at the gateway level               |

### dispute.\*

| Event                  | When it fires                             |
| ---------------------- | ----------------------------------------- |
| `dispute.created`      | Dispute was opened                        |
| `dispute.evidence_due` | Evidence deadline is approaching          |
| `dispute.won`          | Dispute resolved in the merchant's favour |
| `dispute.lost`         | Dispute resolved against the merchant     |

### order.\* (physical products only)

| Event             | When it fires                                      |
| ----------------- | -------------------------------------------------- |
| `order.created`   | Order was placed and paid                          |
| `order.shipped`   | Shipping label generated, tracking available       |
| `order.delivered` | Delivery confirmed                                 |
| `order.refunded`  | Order-level refund (also fires `payment.refunded`) |

***

## Event Payloads

### payment.succeeded

Fired when a payment is completed successfully.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event_type": "payment.succeeded",
  "occurred_at": "2026-03-27T14:32:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "payment",
    "id": "98234",
    "status": "succeeded",
    "payment_type": "one_time",
    "gateway": "paystack",
    "gateway_reference": "ps_ref_abc123",
    "partner_reference": "order_XYZ",
    "amounts": {
      "customer_paid": { "amount": 5000000, "currency": "NGN" },
      "merchant_gross": { "amount": 306, "currency": "USD" },
      "merchant_net": { "amount": 270, "currency": "USD" },
      "fees": {
        "platform_fee": { "amount": 18, "currency": "USD" },
        "gateway_fee": { "amount": 18, "currency": "USD" },
        "total": { "amount": 36, "currency": "USD" }
      },
      "conversion": {
        "from_currency": "NGN",
        "to_currency": "USD",
        "rate": 1630.5,
        "surcharge_percent": 1.0
      }
    },
    "product": {
      "id": "512",
      "title": "Advanced React Course",
      "type": "self_pace_training"
    },
    "customer": {
      "email": "ada@example.com",
      "first_name": "Ada",
      "last_name": "Obi"
    },
    "metadata": { "partner_reference": "order_XYZ" },
    "created_at": "2026-03-27T14:30:00Z",
    "paid_at": "2026-03-27T14:32:00Z"
  }
}
```

<Expandable title="Payment object fields">
  | Field               | Type   | Description                                                                 |
  | ------------------- | ------ | --------------------------------------------------------------------------- |
  | `object`            | string | Always `"payment"`                                                          |
  | `id`                | string | Transaction ID                                                              |
  | `status`            | string | `succeeded`, `failed`, `refunded`, or `disputed`                            |
  | `payment_type`      | string | `one_time`, `subscription`, or `installment`                                |
  | `gateway`           | string | `stripe`, `paystack`, `square`, `paypal`, `startbutton`, or `wallet`        |
  | `gateway_reference` | string | Gateway's transaction/charge ID                                             |
  | `session_id`        | string | Cart identifier (optional)                                                  |
  | `partner_reference` | string | Value passed in `metadata.partner_reference` at session creation (optional) |
  | `amounts`           | object | [MulticurrencyBreakdown](/webhooks/overview#multicurrencybreakdown)         |
  | `product`           | object | Product `id`, `title`, and `type` (optional)                                |
  | `subscription_id`   | string | Present when `payment_type` is `subscription`                               |
  | `installment`       | object | `split_number` and `total_splits` for installment payments                  |
  | `coupon_discount`   | object | [MoneyAmount](/webhooks/overview#moneyamount) if a coupon was applied       |
  | `tax`               | object | [MoneyAmount](/webhooks/overview#moneyamount) if tax was charged            |
  | `shipping`          | object | Shipping cost, tracking number, and carrier (physical products)             |
  | `refund`            | object | Present on `payment.refunded` only (see below)                              |
  | `customer`          | object | Customer `email`, `first_name`, `last_name`, `id`                           |
  | `metadata`          | object | Partner-supplied fields (internal keys stripped)                            |
  | `created_at`        | string | ISO 8601 — when the payment was initiated                                   |
  | `paid_at`           | string | ISO 8601 — when the charge was confirmed (`null` on failed)                 |
</Expandable>

### payment.failed

Fired when a payment attempt fails. Same structure as `payment.succeeded` with `status: "failed"` and `paid_at: null`.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_789_failed",
  "event_type": "payment.failed",
  "occurred_at": "2026-03-27T14:35:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "payment",
    "id": "98235",
    "status": "failed",
    "payment_type": "one_time",
    "gateway": "stripe",
    "gateway_reference": "ch_failed_abc",
    "amounts": {
      "customer_paid": { "amount": 5000, "currency": "USD" },
      "merchant_gross": { "amount": 5000, "currency": "USD" },
      "merchant_net": { "amount": 0, "currency": "USD" },
      "fees": {
        "platform_fee": { "amount": 0, "currency": "USD" },
        "gateway_fee": { "amount": 0, "currency": "USD" },
        "total": { "amount": 0, "currency": "USD" }
      }
    },
    "customer": { "email": "jane@example.com" },
    "created_at": "2026-03-27T14:34:00Z",
    "paid_at": null
  }
}
```

### payment.refunded

Fired when a full or partial refund is processed.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_refund_456",
  "event_type": "payment.refunded",
  "occurred_at": "2026-03-28T10:00:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "payment",
    "id": "98234",
    "status": "refunded",
    "payment_type": "one_time",
    "gateway": "paystack",
    "gateway_reference": "ps_ref_abc123",
    "amounts": {
      "customer_paid": { "amount": 5000000, "currency": "NGN" },
      "merchant_gross": { "amount": 306, "currency": "USD" },
      "merchant_net": { "amount": 270, "currency": "USD" },
      "fees": {
        "platform_fee": { "amount": 18, "currency": "USD" },
        "gateway_fee": { "amount": 18, "currency": "USD" },
        "total": { "amount": 36, "currency": "USD" }
      }
    },
    "refund": {
      "id": "ref_001",
      "refund_amount": { "amount": 270, "currency": "USD" },
      "is_partial": false,
      "reason": "Customer requested"
    },
    "customer": {
      "email": "ada@example.com",
      "first_name": "Ada",
      "last_name": "Obi"
    },
    "created_at": "2026-03-27T14:30:00Z",
    "paid_at": "2026-03-27T14:32:00Z"
  }
}
```

### payment.disputed

Fired when a customer opens a chargeback or dispute. Same payment structure with `status: "disputed"`.

***

### subscription.created

Fired when a new subscription is initiated.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_sub_create_001",
  "event_type": "subscription.created",
  "occurred_at": "2026-03-27T15:00:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "subscription",
    "id": "psub_abc123",
    "status": "active",
    "product": {
      "id": "512",
      "title": "Premium Membership",
      "type": "digital"
    },
    "plan": {
      "interval": "monthly",
      "amount": { "amount": 2999, "currency": "USD" }
    },
    "current_period": {
      "start": "2026-03-27T15:00:00Z",
      "end": "2026-04-27T15:00:00Z"
    },
    "customer": {
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe"
    },
    "created_at": "2026-03-27T15:00:00Z"
  }
}
```

<Expandable title="Subscription object fields">
  | Field                  | Type    | Description                                                                                                     |
  | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------- |
  | `object`               | string  | Always `"subscription"`                                                                                         |
  | `id`                   | string  | Subscription ID (`product_subscription_id`)                                                                     |
  | `status`               | string  | `active`, `trialing`, `past_due`, `cancelled`, or `expired`                                                     |
  | `product`              | object  | Product `id`, `title`, and `type` (optional)                                                                    |
  | `plan.interval`        | string  | `weekly`, `monthly`, `quarterly`, `annually`, etc.                                                              |
  | `plan.amount`          | object  | [MoneyAmount](/webhooks/overview#moneyamount) in merchant's settlement currency                                 |
  | `current_period`       | object  | `start` and `end` ISO 8601 timestamps                                                                           |
  | `trial`                | object  | `start` and `end` timestamps (present during trials)                                                            |
  | `latest_payment_id`    | string  | Present on `renewed` and `payment_failed` events                                                                |
  | `amounts`              | object  | [MulticurrencyBreakdown](/webhooks/overview#multicurrencybreakdown) (present on `renewed` and `payment_failed`) |
  | `cancel_at_period_end` | boolean | Whether cancellation takes effect at period end                                                                 |
  | `cancellation_reason`  | string  | Present on `subscription.cancelled`                                                                             |
  | `customer`             | object  | Customer details                                                                                                |
  | `metadata`             | object  | Partner-supplied fields                                                                                         |
  | `created_at`           | string  | ISO 8601                                                                                                        |
</Expandable>

### subscription.renewed

Fired when a recurring charge succeeds. Includes `latest_payment_id` and `amounts` with the renewal payment breakdown.

### subscription.payment\_failed

Fired when a renewal charge fails. Subscription status changes to `past_due`.

### subscription.cancelled

Fired when a subscription is cancelled (immediately or at period end). Includes `cancellation_reason` if provided.

### subscription.expired

Fired when the subscription period ends without renewal.

### subscription.trial\_started

Fired when a trial period begins. Subscription status is `trialing` and the `trial` object is present.

### subscription.trial\_ending

Fired 3 days before a trial ends — a grace notification to prompt conversion.

### subscription.trial\_ended

Fired when the trial period ends (whether the subscription converted to paid or expired).

***

### wallet.credited

Fired when the merchant wallet is credited (e.g., after a successful sale).

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_wallet_credit_001",
  "event_type": "wallet.credited",
  "occurred_at": "2026-03-27T14:32:05Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "wallet",
    "id": "wt_ref_00112",
    "type": "credit",
    "reason": "sale",
    "amount": { "amount": 4640000, "currency": "NGN" },
    "balance_after": { "amount": 12450000, "currency": "NGN" },
    "related_payment_id": "98234",
    "occurred_at": "2026-03-27T14:32:05Z"
  }
}
```

<Expandable title="Wallet object fields">
  | Field                   | Type   | Description                                                                            |
  | ----------------------- | ------ | -------------------------------------------------------------------------------------- |
  | `object`                | string | Always `"wallet"`                                                                      |
  | `id`                    | string | Wallet transaction reference                                                           |
  | `type`                  | string | `credit` or `debit`                                                                    |
  | `reason`                | string | `sale`, `refund_issued`, `dispute_hold`, `dispute_released`, `payout`, or `adjustment` |
  | `amount`                | object | [MoneyAmount](/webhooks/overview#moneyamount) credited or debited                      |
  | `balance_after`         | object | Wallet balance after this operation                                                    |
  | `original_amount`       | object | Present when currency conversion occurred (e.g., NGN sale → USD wallet)                |
  | `conversion`            | object | `from_currency`, `to_currency`, `rate` — present on cross-currency operations          |
  | `related_payment_id`    | string | Transaction ID if from a sale or refund                                                |
  | `related_dispute_id`    | string | Dispute ID if from a chargeback hold/release                                           |
  | `related_settlement_id` | string | Withdrawal ID if from a payout                                                         |
  | `metadata`              | object | Partner-supplied fields                                                                |
  | `occurred_at`           | string | ISO 8601                                                                               |
</Expandable>

### wallet.debited

Fired when the merchant wallet is debited (refund issued, dispute hold placed, or payout). Same structure as `wallet.credited` with `type: "debit"`.

***

### settlement.initiated

Fired when a payout or withdrawal is requested.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_settle_001",
  "event_type": "settlement.initiated",
  "occurred_at": "2026-03-27T09:00:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "settlement",
    "id": "wd_00445",
    "status": "initiated",
    "gateway": "paystack",
    "payout_method": "transfer",
    "requested": { "amount": 10000000, "currency": "NGN" },
    "fee": { "amount": 53000, "currency": "NGN" },
    "settled": { "amount": 9947000, "currency": "NGN" },
    "initiated_at": "2026-03-27T09:00:00Z"
  }
}
```

<Expandable title="Settlement object fields">
  | Field            | Type   | Description                                                                    |
  | ---------------- | ------ | ------------------------------------------------------------------------------ |
  | `object`         | string | Always `"settlement"`                                                          |
  | `id`             | string | Withdrawal or wallet transaction ID                                            |
  | `status`         | string | `initiated`, `processing`, `completed`, or `failed`                            |
  | `gateway`        | string | `paystack`, `stripe`, `startbutton`, or `gravv`                                |
  | `payout_method`  | string | `transfer` (platform pushes funds) or `payout` (gateway pays directly to bank) |
  | `requested`      | object | [MoneyAmount](/webhooks/overview#moneyamount) the merchant requested           |
  | `fee`            | object | Settlement/transfer fee                                                        |
  | `settled`        | object | Actual amount sent (`requested - fee`)                                         |
  | `cross_currency` | object | Present when wallet currency differs from bank currency (see example below)    |
  | `initiated_at`   | string | ISO 8601                                                                       |
  | `completed_at`   | string | Present on `settlement.completed`                                              |
  | `failure_reason` | string | Present on `settlement.failed`                                                 |
  | `metadata`       | object | Partner-supplied fields                                                        |
</Expandable>

### settlement.completed

Fired when funds are confirmed delivered to the merchant's bank.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_settle_complete_001",
  "event_type": "settlement.completed",
  "occurred_at": "2026-03-27T11:45:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "settlement",
    "id": "wd_00445",
    "status": "completed",
    "gateway": "paystack",
    "payout_method": "transfer",
    "requested": { "amount": 10000000, "currency": "NGN" },
    "fee": { "amount": 53000, "currency": "NGN" },
    "settled": { "amount": 9947000, "currency": "NGN" },
    "initiated_at": "2026-03-27T09:00:00Z",
    "completed_at": "2026-03-27T11:45:00Z"
  }
}
```

**Cross-currency settlement example** (USD wallet to NGN bank account):

```json theme={null}
{
  "data": {
    "object": "settlement",
    "id": "wd_00446",
    "status": "completed",
    "gateway": "paystack",
    "payout_method": "transfer",
    "requested": { "amount": 50000, "currency": "USD" },
    "fee": { "amount": 500, "currency": "USD" },
    "settled": { "amount": 49500, "currency": "USD" },
    "cross_currency": {
      "source": { "amount": 49500, "currency": "USD" },
      "destination": { "amount": 80752500, "currency": "NGN" },
      "rate": 1631.36
    },
    "initiated_at": "2026-03-27T09:00:00Z",
    "completed_at": "2026-03-27T12:10:00Z"
  }
}
```

### settlement.processing

Fired when the gateway confirms the payout is being processed.

### settlement.failed

Fired when a payout fails at the gateway level. Includes `failure_reason`.

***

### dispute.created

Fired when a dispute is opened on a payment.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_dispute_001",
  "event_type": "dispute.created",
  "occurred_at": "2026-03-28T09:00:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "dispute",
    "id": "disp_001",
    "status": "needs_response",
    "reason": "product_not_received",
    "gateway": "stripe",
    "gateway_dispute_id": "dp_abc123",
    "disputed_amount": { "amount": 5000, "currency": "USD" },
    "chargeback_fee": { "amount": 1500, "currency": "USD" },
    "hold_amount": { "amount": 6500, "currency": "USD" },
    "related_payment_id": "98234",
    "evidence_due_by": "2026-04-11T23:59:59Z",
    "customer": {
      "email": "ada@example.com",
      "first_name": "Ada",
      "last_name": "Obi"
    },
    "occurred_at": "2026-03-28T09:00:00Z"
  }
}
```

<Expandable title="Dispute object fields">
  | Field                | Type   | Description                                                                       |
  | -------------------- | ------ | --------------------------------------------------------------------------------- |
  | `object`             | string | Always `"dispute"`                                                                |
  | `id`                 | string | Dispute record ID                                                                 |
  | `status`             | string | `needs_response`, `funds_withdrawn`, `under_review`, `won`, `lost`, or `accepted` |
  | `reason`             | string | `fraudulent`, `product_not_received`, `duplicate`, etc.                           |
  | `gateway`            | string | Gateway where the dispute was filed                                               |
  | `gateway_dispute_id` | string | Gateway's dispute ID                                                              |
  | `disputed_amount`    | object | [MoneyAmount](/webhooks/overview#moneyamount) being disputed                      |
  | `chargeback_fee`     | object | Fee charged by the gateway for the dispute                                        |
  | `hold_amount`        | object | Total held from merchant wallet (`disputed_amount + chargeback_fee`)              |
  | `related_payment_id` | string | Transaction ID of the original charge                                             |
  | `evidence_due_by`    | string | ISO 8601 deadline for submitting evidence                                         |
  | `resolution`         | string | `won` or `lost` — present on `dispute.won` and `dispute.lost`                     |
  | `customer`           | object | Customer details                                                                  |
  | `occurred_at`        | string | ISO 8601                                                                          |
</Expandable>

### dispute.evidence\_due

Fired when the evidence deadline is approaching.

### dispute.won

Fired when the dispute is resolved in the merchant's favour. Held funds are released.

### dispute.lost

Fired when the dispute is resolved against the merchant.

***

### order.created

Fired when a physical product order is placed and paid.

```json theme={null}
{
  "api_version": "2026-03-27",
  "event_id": "evt_order_001",
  "event_type": "order.created",
  "occurred_at": "2026-03-27T16:00:00Z",
  "is_live": true,
  "business_id": "1042",
  "data": {
    "object": "order",
    "id": "98240",
    "status": "created",
    "amounts": {
      "customer_paid": { "amount": 7500, "currency": "USD" },
      "merchant_gross": { "amount": 7500, "currency": "USD" },
      "merchant_net": { "amount": 6900, "currency": "USD" },
      "fees": {
        "platform_fee": { "amount": 300, "currency": "USD" },
        "gateway_fee": { "amount": 300, "currency": "USD" },
        "total": { "amount": 600, "currency": "USD" }
      }
    },
    "product": {
      "id": "800",
      "title": "Wireless Headphones",
      "type": "physical_product"
    },
    "shipping": {},
    "customer": {
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "shipping_address": {
        "line1": "123 Main St",
        "city": "Austin",
        "state": "TX",
        "postal_code": "78701",
        "country": "US"
      }
    },
    "created_at": "2026-03-27T16:00:00Z"
  }
}
```

<Expandable title="Order object fields">
  | Field                         | Type   | Description                                                                      |
  | ----------------------------- | ------ | -------------------------------------------------------------------------------- |
  | `object`                      | string | Always `"order"`                                                                 |
  | `id`                          | string | Transaction ID of the purchase                                                   |
  | `status`                      | string | `created`, `shipped`, `delivered`, or `refunded`                                 |
  | `amounts`                     | object | [MulticurrencyBreakdown](/webhooks/overview#multicurrencybreakdown)              |
  | `product`                     | object | Product `id`, `title`, and `type` (always `physical_product`)                    |
  | `shipping.carrier`            | string | Shipping carrier name                                                            |
  | `shipping.tracking_number`    | string | Tracking number (from `order.shipped` onwards)                                   |
  | `shipping.tracking_url`       | string | URL to track the shipment                                                        |
  | `shipping.estimated_delivery` | string | ISO 8601 estimated delivery date                                                 |
  | `shipping.shipped_at`         | string | ISO 8601 (from `order.shipped` onwards)                                          |
  | `shipping.delivered_at`       | string | ISO 8601 (on `order.delivered`)                                                  |
  | `customer.shipping_address`   | object | `line1`, `line2`, `city`, `state`, `postal_code`, `country` (ISO 3166-1 alpha-2) |
  | `refund_id`                   | string | Present on `order.refunded`                                                      |
  | `metadata`                    | object | Partner-supplied fields                                                          |
  | `created_at`                  | string | ISO 8601                                                                         |
</Expandable>

### order.shipped

Fired when a shipping label is generated and tracking is available. Includes `shipping.tracking_number`, `shipping.carrier`, and `shipping.shipped_at`.

### order.delivered

Fired when delivery is confirmed. Includes `shipping.delivered_at`.

### order.refunded

Fired on an order-level refund. Also fires a `payment.refunded` event for the associated payment.
