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

# Cancel Subscription

> Cancel an active subscription.

Cancels a subscription. For **recurring** (Stripe-managed) subscriptions, the status moves to `pending_cancel` and access continues until the end of the current billing period. For **manual** billing subscriptions, the status moves to `canceled` immediately.

## Path Parameters

<ParamField path="subscriptionId" type="string" required>
  The Crovver subscription ID
</ParamField>

## Request Body

<ParamField body="externalTenantId" type="string" required>
  The external tenant ID from your application. Used to verify the subscription belongs to this tenant.
</ParamField>

<ParamField body="reason" type="string" required>
  Cancellation reason. One of: `too_expensive`, `missing_features`, `switching_provider`, `not_using`, `other`
</ParamField>

<ParamField body="feedback" type="string">
  Optional free-text feedback from the user
</ParamField>

## Authentication

Requires a **secret key** (`Authorization: Bearer sk_live_...`) or **service key** (`x-service-key`).

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://app.crovver.com/api/public/subscriptions/56e0d8e3-6731-4b1c-b01a-73b561b1cd47/cancel" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "externalTenantId": "workspace_123",
      "reason": "too_expensive",
      "feedback": "Would come back at a lower price point"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Recurring subscription (access continues until period end) theme={null}
  {
    "success": true,
    "data": {
      "subscriptionId": "56e0d8e3-6731-4b1c-b01a-73b561b1cd47",
      "status": "pending_cancel",
      "canceledAt": "2026-05-18T12:00:00Z",
      "currentPeriodEnd": "2026-06-10T05:12:21.000Z"
    }
  }
  ```

  ```json 200 Manual billing subscription (canceled immediately) theme={null}
  {
    "success": true,
    "data": {
      "subscriptionId": "56e0d8e3-6731-4b1c-b01a-73b561b1cd47",
      "status": "canceled",
      "canceledAt": "2026-05-18T12:00:00Z",
      "currentPeriodEnd": "2026-06-10T05:12:21.000Z"
    }
  }
  ```

  ```json 400 Already canceled theme={null}
  {
    "success": false,
    "error": {
      "message": "Subscription is already canceled or pending cancellation",
      "code": "ALREADY_CANCELED"
    }
  }
  ```
</ResponseExample>
