> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.coinflow.cash/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server.

# Enabling Customers to Cancel Subscriptions

## Overview

Allowing customers to cancel their subscriptions is essential for a good user experience and helps reduce chargebacks. Coinflow provides simple APIs to enable subscription cancellation in two ways:

## Cancellation Methods

### Two Approaches to Cancellation

1. **Customer-Initiated Cancellation** - Customers cancel through your application using their session key
2. **Merchant-Initiated Cancellation** - Merchants cancel on behalf of customers using the merchant API

## Customer-Initiated Cancellation

### Step 1: Get Customer's Subscriptions

First, retrieve all active subscriptions for the customer:

```javascript
// API Reference: /api-reference/api-reference/customers/get-customersubscriptions

const response = await fetch(
  'https://api-sandbox.coinflow.cash/api/subscription/{merchantId}/subscribers',
  {
    method: 'GET',
    headers: {
      'accept': 'application/json',
      'x-coinflow-auth-session-key': sessionKey
    }
  }
);

const subscriptions = await response.json();
```

**Example Response:**

```json
[
  {
    "id": "6851d8c378269da7d5a535d6",
    "customerId": "customer123",
    "merchantId": "your-merchant-id",
    "email": "customer@example.com",
    "plan": "Premium Plan",
    "planCode": "premium-monthly",
    "status": "Active",
    "createdAt": "2024-01-15T10:30:00Z",
    "nextBillingDate": "2024-02-15T10:30:00Z"
  }
]
```

### Step 2: Cancel the Subscription

Use the subscription ID to cancel:

```javascript
// API Reference: /api-reference/api-reference/subscription/cancel-customer-subscription

const response = await fetch(
  `https://api-sandbox.coinflow.cash/api/subscription/{merchantId}/subscribers/{subscriptionId}`,
  {
    method: 'PATCH',
    headers: {
      'x-coinflow-auth-session-key': sessionKey
    }
  }
);

if (response.ok) {
  console.log('Subscription cancelled successfully');
}
```

### Building a Cancellation UI

Here's an example React component for subscription cancellation:

```javascript
import { useState, useEffect } from 'react';

function SubscriptionManager({ sessionKey, merchantId }) {
  const [subscriptions, setSubscriptions] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchSubscriptions();
  }, []);

  const fetchSubscriptions = async () => {
    try {
      const response = await fetch(
        `https://api-sandbox.coinflow.cash/api/subscription/${merchantId}/subscribers`,
        {
          headers: {
            'x-coinflow-auth-session-key': sessionKey
          }
        }
      );
      const data = await response.json();
      setSubscriptions(data);
    } catch (error) {
      console.error('Error fetching subscriptions:', error);
    } finally {
      setLoading(false);
    }
  };

  const cancelSubscription = async (subscriptionId) => {
    if (!confirm('Are you sure you want to cancel this subscription?')) {
      return;
    }

    try {
      const response = await fetch(
        `https://api-sandbox.coinflow.cash/api/subscription/${merchantId}/subscribers/${subscriptionId}`,
        {
          method: 'PATCH',
          headers: {
            'x-coinflow-auth-session-key': sessionKey
          }
        }
      );

      if (response.ok) {
        alert('Subscription cancelled successfully');
        fetchSubscriptions(); // Refresh the list
      }
    } catch (error) {
      console.error('Error cancelling subscription:', error);
      alert('Failed to cancel subscription');
    }
  };

  if (loading) {
    return <div>Loading subscriptions...</div>;
  }

  return (
    <div>
      <h2>Your Subscriptions</h2>
      {subscriptions.map(sub => (
        <div key={sub.id} className="subscription-card">
          <h3>{sub.plan}</h3>
          <p>Status: {sub.status}</p>
          <p>Next billing: {new Date(sub.nextBillingDate).toLocaleDateString()}</p>
          {sub.status === 'Active' && (
            <button onClick={() => cancelSubscription(sub.id)}>
              Cancel Subscription
            </button>
          )}
        </div>
      ))}
    </div>
  );
}
```

## Merchant-Initiated Cancellation

Merchants can cancel subscriptions on behalf of customers using the merchant API:

```javascript
// API Reference: /api/cancelsubscription

const response = await fetch(
  `https://api-sandbox.coinflow.cash/api/merchant/subscription/subscribers/{subscriptionId}`,
  {
    method: 'PATCH',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    }
  }
);
```

This is useful for:

* Customer support scenarios
* Policy violations
* Refund situations
* Account closures

## Cancellation via Merchant Dashboard

Merchants can also cancel subscriptions through the Coinflow merchant dashboard:

1. Log in to [merchant dashboard](https://sandbox-merchant.coinflow.cash)
2. Navigate to **Subscriptions**
3. Click on the subscription plan
4. Find the subscriber in the list
5. Click **Cancel Subscription**

## Cancellation Behavior

### What Happens When a Subscription is Cancelled

When a subscription is cancelled:

* **Status Update**: Changes to `Canceled`
* **Billing**: No future payments will be processed
* **Access**: Customer typically retains access until end of current billing period
* **Notifications**: Cancellation webhook is triggered

### Configuring Access After Cancellation

You can implement different access policies:

1. **Immediate Termination** - Access ends immediately upon cancellation
2. **End of Period** - Access continues until the end of the current billing period (recommended)
3. **Grace Period** - Custom grace period after cancellation

Implement your preferred policy in your application logic using the cancellation timestamp and next billing date from the subscription data.

## Handling Cancellation Webhooks

Set up webhooks to receive cancellation notifications:

```javascript
// Webhook payload for subscription cancellation
{
  "event": "subscription.cancelled",
  "data": {
    "subscriptionId": "6851d8c378269da7d5a535d6",
    "customerId": "customer123",
    "planCode": "premium-monthly",
    "cancelledAt": "2024-01-20T15:45:00Z",
    "reason": "customer_requested"
  }
}
```

Handle the webhook in your backend:

```javascript
app.post('/webhooks/coinflow', (req, res) => {
  const event = req.body;

  if (event.event === 'subscription.cancelled') {
    const { subscriptionId, customerId } = event.data;

    // Update your database
    await db.subscriptions.update({
      where: { id: subscriptionId },
      data: { status: 'cancelled', cancelledAt: new Date() }
    });

    // Send cancellation email to customer
    await sendCancellationEmail(customerId);

    // Log for analytics
    analytics.track('Subscription Cancelled', {
      subscriptionId,
      customerId
    });
  }

  res.sendStatus(200);
});
```

## Best Practices

### Clear Communication

* Explain what happens when they cancel
* Show when access will end
* Offer alternatives (pause, downgrade)
* Request feedback on why they're cancelling

### Retention Strategies

Before cancelling, consider:

* Offering a discount or special offer
* Suggesting a pause instead of cancel
* Downgrading to a lower tier
* Providing a feedback form

### User Experience

* Make cancellation easy to find (don't hide it)
* Require confirmation but don't make it difficult
* Send confirmation email after cancellation
* Allow easy reactivation

### Example Cancellation Flow

```javascript
function CancellationFlow({ subscription, onCancel }) {
  const [step, setStep] = useState('confirm');
  const [feedback, setFeedback] = useState('');

  const handleConfirm = () => {
    setStep('feedback');
  };

  const handleSubmit = async () => {
    // Submit feedback (optional)
    if (feedback) {
      await submitCancellationFeedback(subscription.id, feedback);
    }

    // Proceed with cancellation
    await onCancel(subscription.id);
    setStep('complete');
  };

  if (step === 'confirm') {
    return (
      <div>
        <h3>Cancel {subscription.plan}?</h3>
        <p>Your subscription will remain active until {subscription.nextBillingDate}</p>
        <button onClick={handleConfirm}>Yes, Cancel</button>
        <button onClick={() => window.history.back()}>Keep Subscription</button>
      </div>
    );
  }

  if (step === 'feedback') {
    return (
      <div>
        <h3>Help us improve</h3>
        <p>Why are you cancelling? (optional)</p>
        <textarea
          value={feedback}
          onChange={(e) => setFeedback(e.target.value)}
          placeholder="Your feedback..."
        />
        <button onClick={handleSubmit}>Complete Cancellation</button>
      </div>
    );
  }

  return (
    <div>
      <h3>Subscription Cancelled</h3>
      <p>You'll have access until {subscription.nextBillingDate}</p>
      <p>You can reactivate anytime from your account settings.</p>
    </div>
  );
}
```

## Reactivating Cancelled Subscriptions

Customers may want to reactivate a cancelled subscription. You'll need to create a new subscription using the same plan code:

```javascript
// Create a new subscription with the same plan
const response = await fetch(
  'https://api-sandbox.coinflow.cash/api/subscription/{merchantId}/subscribers/card',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-coinflow-auth-session-key': sessionKey
    },
    body: JSON.stringify({
      planCode: previousPlanCode,
      card: savedCardToken,
      // ... other required fields
    })
  }
);
```

## Related Resources

* [Subscription Webhooks](/guides/subscriptions/implementation-methods/api-integration#webhooks)
* [Managing Subscription Plans](/guides/subscriptions/overview/understanding-your-flow-of-funds/managing-subscription-plans-subscribers)
* [API Reference - Cancel Subscription](/api-reference/api-reference/subscription/cancel-customer-subscription)