---
title: "Cancel subscription"
method: POST
path: "/api/billing/cancel"
tags: ["billing", "internal"]
---

# Cancel subscription

`POST /api/billing/cancel`

In-app cancel modal endpoint. Sets Stripe `cancel_at` to the current
period end (via Stripe's `MaxPeriodEnd` sentinel), stashes the canonical
Scanopy reason in subscription metadata, returns the period end so the
modal can render the retention disclosure.

## Request body

- CancelSubscriptionRequest
  - `comment` string, nullable — Free-text detail the customer added to their cancellation reason.
  - `reason_code` 'too_expensive' | 'missing_features' | 'switched_service' | 'unused' | 'customer_service' | 'low_quality' | 'too_complex' | 'other', required — Cancellation reason captured in `SubscriptionCancelled` / `CancellationInitiated` events. Mirrors the values surfaced in the in-app cancel flow (Phase 5).
  - `save_offer_redeemed` 'pause' | 'discount' | 'downgrade' — Save-offer choices presented during in-app cancellation (Phase 5).
  - `save_offer_shown` SaveOffer[] — Whether the retention discount was offered during this flow.

## Response `200`

Cancellation initiated

- ApiResponseCancelSubscriptionResponse
  - `data` object — The result payload. Omitted on failure.
    - `period_end` string, date-time, required — When the current paid period ends and access drops to the free tier.
  - `error` string, nullable — Human-readable failure message. Omitted on success.
  - `meta` ApiMeta, required — API metadata included in all responses
    - `api_version` integer, required — API version (integer, increments on breaking changes)
    - `server_version` string, required — Server version (semver)
  - `success` boolean, required — `true` when the request succeeded. `false` responses carry `error` instead of `data`.

## Other responses

- `400` — No active subscription or billing not enabled

---

[API](https://skmtc.net/scanopy/apis/scanopy-api.md) · [All operations](https://skmtc.net/scanopy/apis/scanopy-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/scanopy/scanopy-api/revisions/2df1fc47dfa7/schema)
