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

# Pemulihan

> Payload yang dikirim ke endpoint webhook Anda ketika pemulihan keranjang yang ditinggalkan atau peristiwa dunning langganan terjadi.

## Peristiwa Pemulihan Keranjang yang Ditinggalkan

Peristiwa webhook berikut melacak siklus hidup pemulihan keranjang yang ditinggalkan:

| Peristiwa                      | Deskripsi                                                                                                                                                             |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `abandoned_checkout.detected`  | Checkout yang ditinggalkan telah terdeteksi. Dikirim saat pembayaran diidentifikasi sebagai ditinggalkan (gagal atau tidak lengkap) dan alur kerja pemulihan dimulai. |
| `abandoned_checkout.recovered` | Pelanggan menyelesaikan pembayaran melalui tautan pemulihan. Kolom `recovered_payment_id` berisi ID pembayaran yang berhasil.                                         |

### Bidang Payload Checkout yang Ditinggalkan

<ParamField body="payment_id" type="string" required>
  Pembayaran asli yang ditinggalkan. Gunakan ini untuk mencari detail produk, jumlah, dan mata uang.
</ParamField>

<ParamField body="customer_id" type="string" required>
  Pelanggan yang meninggalkan checkout.
</ParamField>

<ParamField body="abandonment_reason" type="string" required>
  Mengapa checkout ditinggalkan. Salah satu dari:

  * `payment_failed` — Pelanggan mencoba pembayaran tetapi gagal
  * `checkout_incomplete` — Pelanggan mengunjungi checkout tetapi tidak pernah mencoba pembayaran
</ParamField>

<ParamField body="status" type="string" required>
  Status siklus hidup saat ini dari upaya pemulihan ini. Salah satu dari:

  * `abandoned` — Terdeteksi, belum ada email yang dikirim
  * `recovering` — Setidaknya satu email pemulihan terkirim
  * `recovered` — Pelanggan menyelesaikan pembayaran
  * `exhausted` — Semua email terkirim atau checkout baru ditemukan
  * `opted_out` — Pelanggan berhenti berlangganan
</ParamField>

<ParamField body="abandoned_at" type="string" required>
  Timestamp ISO 8601 ketika checkout terdeteksi sebagai ditinggalkan.
</ParamField>

<ParamField body="recovered_payment_id" type="string | null">
  ID pembayaran dari pembayaran pemulihan yang berhasil. `null` sampai checkout dipulihkan.
</ParamField>

### Contoh: Menangani Webhook ACR

```javascript theme={null}
app.post('/webhooks/dodo', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'abandoned_checkout.detected':
      console.log(`Checkout abandoned: ${event.data.payment_id}`);
      console.log(`Reason: ${event.data.abandonment_reason}`);
      // Track abandonment in your analytics
      await trackAbandonment(event.data);
      break;

    case 'abandoned_checkout.recovered':
      console.log(`Checkout recovered: ${event.data.payment_id}`);
      console.log(`Recovery payment: ${event.data.recovered_payment_id}`);
      // Grant access, update records
      await handleRecovery(event.data);
      break;
  }

  res.json({ received: true });
});
```

***

## Peristiwa Dunning

Peristiwa webhook berikut melacak siklus hidup dunning langganan:

| Peristiwa           | Deskripsi                                                                                                                                      |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `dunning.started`   | Percobaan dunning telah dibuat untuk langganan yang masuk ke `on_hold` atau dibatalkan oleh pelanggan.                                         |
| `dunning.recovered` | Pelanggan memperbarui metode pembayaran mereka dan pembayaran yang dihasilkan berhasil. Kolom `payment_id` berisi ID pembayaran yang berhasil. |

### Bidang Payload Percobaan Dunning

<ParamField body="subscription_id" type="string" required>
  Langganan yang memicu percobaan dunning.
</ParamField>

<ParamField body="customer_id" type="string" required>
  Pelanggan yang memiliki langganan.
</ParamField>

<ParamField body="trigger_state" type="string" required>
  Status langganan yang memicu dunning. Salah satu dari:

  * `on_hold` — Langganan dijeda karena kegagalan pembayaran
  * `cancelled` — Pelanggan membatalkan dari portal pelanggan
</ParamField>

<ParamField body="status" type="string" required>
  Status siklus hidup saat ini dari percobaan dunning ini. Salah satu dari:

  * `recovering` — Email dunning sedang dikirim
  * `recovered` — Pelanggan memperbarui metode pembayaran dan pembayaran berhasil
  * `exhausted` — Semua email terkirim atau status langganan berubah
</ParamField>

<ParamField body="created_at" type="string" required>
  Timestamp ISO 8601 ketika percobaan dunning dibuat.
</ParamField>

<ParamField body="payment_id" type="string | null">
  ID pembayaran dari pembayaran pemulihan yang berhasil. `null` saat pemulihan.
</ParamField>

### Contoh: Menangani Webhook Dunning

```javascript theme={null}
app.post('/webhooks/dodo', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'dunning.started':
      console.log(`Dunning started for subscription: ${event.data.subscription_id}`);
      console.log(`Trigger: ${event.data.trigger_state}`);
      // Track dunning in your system
      await trackDunning(event.data);
      break;

    case 'dunning.recovered':
      console.log(`Subscription recovered: ${event.data.subscription_id}`);
      console.log(`Recovery payment: ${event.data.payment_id}`);
      // Reactivate access, update records
      await handleDunningRecovery(event.data);
      break;
  }

  res.json({ received: true });
});
```

<Tip>
  Berlangganan ke `dunning.started` dan `dunning.recovered` untuk melacak siklus hidup dunning lengkap. Gunakan `dunning.started` untuk menjeda periode tenggang atau menandai langganan berisiko dalam sistem Anda.
</Tip>

<CardGroup cols={2}>
  <Card title="Abandoned Cart Recovery" icon="cart-shopping" href="/features/recovery/abandoned-cart-recovery">
    Konfigurasi urutan email ACR dan insentif diskon.
  </Card>

  <Card title="Subscription Dunning" icon="rotate" href="/features/recovery/subscription-dunning">
    Konfigurasi urutan email dunning untuk langganan yang terlewat.
  </Card>

  <Card title="Subscription Webhooks" icon="repeat" href="/developer-resources/webhooks/intents/subscription">
    Peristiwa siklus hidup langganan terkait seperti `subscription.on_hold` dan `subscription.cancelled`.
  </Card>
</CardGroup>

## Skema Payload Webhook
