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

# Recovery

> 장바구니 복구 또는 구독 경고 이벤트가 발생할 때 웹훅 엔드포인트에 전송되는 페이로드입니다.

## 장바구니 복구 이벤트

다음 웹훅 이벤트는 장바구니 복구 수명 주기를 추적합니다:

| Event                          | Description                                                                  |
| ------------------------------ | ---------------------------------------------------------------------------- |
| `abandoned_checkout.detected`  | 방치된 결제가 감지되었습니다. 결제가 방치(실패 또는 불완전)로 식별되고 복구 워크플로가 시작되면 전송됩니다.                |
| `abandoned_checkout.recovered` | 고객이 복구 링크를 통해 결제를 완료했습니다. `recovered_payment_id` 필드에는 성공적인 결제 ID가 포함되어 있습니다. |

### 방치된 결제 페이로드 필드

<ParamField body="payment_id" type="string" required>
  방치된 원래 결제입니다. 이를 사용하여 제품, 금액 및 통화 세부 정보를 조회할 수 있습니다.
</ParamField>

<ParamField body="customer_id" type="string" required>
  결제를 방치한 고객입니다.
</ParamField>

<ParamField body="abandonment_reason" type="string" required>
  결제가 방치된 이유입니다. 다음 중 하나:

  * `payment_failed` — 고객이 결제를 시도했지만 실패
  * `checkout_incomplete` — 고객이 결제 페이지에 방문했지만 결제를 시도하지 않음
</ParamField>

<ParamField body="status" type="string" required>
  이 복구 시도의 현재 수명 주기 상태입니다. 다음 중 하나:

  * `abandoned` — 감지됨, 아직 이메일 전송 안 됨
  * `recovering` — 최소한 하나의 복구 이메일이 전송됨
  * `recovered` — 고객이 결제를 완료함
  * `exhausted` — 모든 이메일이 전송되었거나 새로운 결제가 발견됨
  * `opted_out` — 고객이 구독 취소함
</ParamField>

<ParamField body="abandoned_at" type="string" required>
  방치된 결제가 감지된 시점의 ISO 8601 타임스탬프입니다.
</ParamField>

<ParamField body="recovered_payment_id" type="string | null">
  성공적인 복구 결제의 결제 ID입니다. 체크아웃이 복구될 때까지 `null`.
</ParamField>

### 예제: 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 });
});
```

***

## 경고 이벤트

다음 웹훅 이벤트는 구독 경고 수명 주기를 추적합니다:

| Event               | Description                                                               |
| ------------------- | ------------------------------------------------------------------------- |
| `dunning.started`   | 구독이 `on_hold` 상태로 들어가거나 고객에 의해 취소된 경우 경고 시도가 생성됩니다.                       |
| `dunning.recovered` | 고객이 결제 방법을 업데이트하고 결과 결제가 성공했습니다. `payment_id` 필드에는 성공적인 결제 ID가 포함되어 있습니다. |

### 경고 시도 페이로드 필드

<ParamField body="subscription_id" type="string" required>
  경고 시도를 트리거한 구독입니다.
</ParamField>

<ParamField body="customer_id" type="string" required>
  구독을 소유한 고객입니다.
</ParamField>

<ParamField body="trigger_state" type="string" required>
  경고를 트리거한 구독 상태입니다. 다음 중 하나:

  * `on_hold` — 결제 실패로 인해 구독이 일시 중지됨
  * `cancelled` — 고객 포털에서 고객이 취소함
</ParamField>

<ParamField body="status" type="string" required>
  이 경고 시도의 현재 수명 주기 상태입니다. 다음 중 하나:

  * `recovering` — 경고 이메일 전송 중
  * `recovered` — 고객이 결제 방법을 업데이트하고 결제가 성공함
  * `exhausted` — 모든 이메일이 전송되었거나 구독 상태가 변경됨
</ParamField>

<ParamField body="created_at" type="string" required>
  경고 시도가 생성된 시점의 ISO 8601 타임스탬프입니다.
</ParamField>

<ParamField body="payment_id" type="string | null">
  성공적인 복구 결제의 결제 ID입니다. 복구 중일 때까지 `null`.
</ParamField>

### 예제: 경고 웹훅 처리

```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>
  전체 경고 수명 주기를 추적하기 위해 `dunning.started`와 `dunning.recovered` 모두를 구독하십시오. 시스템에서 유예 기간을 일시 중지하거나 위험 구독을 플래그하기 위해 `dunning.started`를 사용하십시오.
</Tip>

<CardGroup cols={2}>
  <Card title="Abandoned Cart Recovery" icon="cart-shopping" href="/features/recovery/abandoned-cart-recovery">
    ACR 이메일 시퀀스 및 할인 인센티브 구성.
  </Card>

  <Card title="Subscription Dunning" icon="rotate" href="/features/recovery/subscription-dunning">
    구독 만료에 대한 경고 이메일 시퀀스 구성.
  </Card>

  <Card title="Subscription Webhooks" icon="repeat" href="/developer-resources/webhooks/intents/subscription">
    관련 구독 수명 주기 이벤트, 예를 들어 `subscription.on_hold`과 `subscription.cancelled`.
  </Card>
</CardGroup>

## 웹훅 페이로드 스키마
