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

# Churn Events

> Create, list, and manage churn events.

# Churn Events

Churn events represent customer cancellations and failed payments. Each event triggers AI-powered recovery workflows.

## Event Status Lifecycle

Every churn event moves through a defined lifecycle:

```
new → processing → variants_generated → email_sent → recovered / lost
```

| Status               | Description                                    |
| -------------------- | ---------------------------------------------- |
| `new`                | Event received, waiting to be processed        |
| `processing`         | AI is analyzing the event and customer data    |
| `variants_generated` | 9 recovery email variants have been generated  |
| `email_sent`         | A recovery email has been sent to the customer |
| `recovered`          | Customer reactivated or payment succeeded      |
| `lost`               | Recovery window expired without reactivation   |

***

## Create a Churn Event

Create a new churn event manually (alternative to webhooks).

```
POST /projects/:slug/churn-events
```

### Request Body

<ParamField body="customer_email" type="string" required>
  Customer's email address.
</ParamField>

<ParamField body="customer_name" type="string">
  Customer's display name.
</ParamField>

<ParamField body="event_type" type="string" required>
  Type of churn: `cancellation` or `payment_failed`.
</ParamField>

<ParamField body="cancel_reason" type="string">
  Free-text reason for cancellation. Drives AI strategy selection.
</ParamField>

<ParamField body="mrr" type="integer">
  Monthly recurring revenue in cents.
</ParamField>

<ParamField body="currency" type="string">
  ISO 4217 currency code. Defaults to `usd`.
</ParamField>

<ParamField body="plan_name" type="string">
  Subscription plan name.
</ParamField>

<ParamField body="tenure_days" type="integer">
  Days the customer has been subscribed.
</ParamField>

### Example Request

```bash theme={null}
curl -X POST https://api.windbackai.com/api/v1/projects/my-project/churn-events \
  -H "X-API-Key: sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_email": "jane@example.com",
    "customer_name": "Jane Smith",
    "event_type": "cancellation",
    "cancel_reason": "Too expensive for our team",
    "mrr": 4999,
    "currency": "usd",
    "plan_name": "Team Pro",
    "tenure_days": 180
  }'
```

### Example Response

```json theme={null}
{
  "data": {
    "id": "evt_abc123",
    "project_id": "prj_xyz",
    "customer_email": "jane@example.com",
    "customer_name": "Jane Smith",
    "event_type": "cancellation",
    "cancel_reason": "Too expensive for our team",
    "status": "new",
    "mrr": 4999,
    "currency": "usd",
    "plan_name": "Team Pro",
    "tenure_days": 180,
    "provider": "api",
    "created_at": "2025-12-01T10:00:00Z",
    "updated_at": "2025-12-01T10:00:00Z"
  }
}
```

***

## List Churn Events

Retrieve a paginated list of churn events for a project.

```
GET /projects/:slug/churn-events
```

### Query Parameters

<ParamField query="page" type="integer" default="1">
  Page number.
</ParamField>

<ParamField query="per_page" type="integer" default="20">
  Items per page (max 100).
</ParamField>

<ParamField query="status" type="string">
  Filter by status: `new`, `processing`, `variants_generated`, `email_sent`, `recovered`, `lost`.
</ParamField>

<ParamField query="event_type" type="string">
  Filter by type: `cancellation` or `payment_failed`.
</ParamField>

### Example Request

```bash theme={null}
curl "https://api.windbackai.com/api/v1/projects/my-project/churn-events?status=new&page=1&per_page=10" \
  -H "X-API-Key: sk_live_abc123..."
```

### Example Response

```json theme={null}
{
  "data": [
    {
      "id": "evt_abc123",
      "customer_email": "jane@example.com",
      "event_type": "cancellation",
      "status": "new",
      "mrr": 4999,
      "created_at": "2025-12-01T10:00:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 10,
    "total": 42
  }
}
```

***

## Get a Churn Event

Retrieve a single churn event by ID.

```
GET /projects/:slug/churn-events/:id
```

### Example Request

```bash theme={null}
curl https://api.windbackai.com/api/v1/projects/my-project/churn-events/evt_abc123 \
  -H "X-API-Key: sk_live_abc123..."
```

### Example Response

```json theme={null}
{
  "data": {
    "id": "evt_abc123",
    "project_id": "prj_xyz",
    "customer_email": "jane@example.com",
    "customer_name": "Jane Smith",
    "event_type": "cancellation",
    "cancel_reason": "Too expensive for our team",
    "status": "variants_generated",
    "mrr": 4999,
    "currency": "usd",
    "plan_name": "Team Pro",
    "tenure_days": 180,
    "provider": "stripe",
    "variants": [
      {
        "id": "var_001",
        "strategy": "value_recap",
        "subject": "Jane, here's what you'll miss",
        "body": "Hi Jane, ...",
        "status": "draft"
      }
    ],
    "created_at": "2025-12-01T10:00:00Z",
    "updated_at": "2025-12-01T10:05:00Z"
  }
}
```

***

## Mark as Recovered

Mark a churn event as recovered when the customer reactivates.

```
POST /projects/:slug/churn-events/:id/recovered
```

### Example Request

```bash theme={null}
curl -X POST https://api.windbackai.com/api/v1/projects/my-project/churn-events/evt_abc123/recovered \
  -H "X-API-Key: sk_live_abc123..."
```

### Example Response

```json theme={null}
{
  "data": {
    "id": "evt_abc123",
    "status": "recovered",
    "recovered_at": "2025-12-05T14:30:00Z"
  }
}
```

<Note>
  Stripe and Razorpay integrations automatically mark events as recovered when a `payment_succeeded` or `payment.captured` event is received.
</Note>

***

## Update Cancel Reason

Update the cancel reason on an existing churn event. Useful when the reason is collected after the event is created.

```
PATCH /projects/:slug/churn-events/:id/cancel-reason
```

### Request Body

<ParamField body="cancel_reason" type="string" required>
  The updated cancel reason.
</ParamField>

### Example Request

```bash theme={null}
curl -X PATCH https://api.windbackai.com/api/v1/projects/my-project/churn-events/evt_abc123/cancel-reason \
  -H "X-API-Key: sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"cancel_reason": "Switching to a competitor with better integrations"}'
```

### Example Response

```json theme={null}
{
  "data": {
    "id": "evt_abc123",
    "cancel_reason": "Switching to a competitor with better integrations",
    "updated_at": "2025-12-01T11:00:00Z"
  }
}
```
