---
title: "Cancel Subscription"
method: POST
path: "/api/billing/cancel"
tags: ["billing"]
---

# Cancel Subscription

`POST /api/billing/cancel`

## Request

- Base URL: `https://kernelscan.io`
- URL: `https://kernelscan.io/api/billing/cancel`
- Auth: none declared

Stop the subscription renewing; the plan runs to the end of the period.

Deliberately not an immediate downgrade. The period is paid for, and taking
the plan away the moment someone clicks cancel would be charging for time
then withholding it. The drop to free happens when Stripe fires
``customer.subscription.deleted`` at the period end, on the same webhook
path as any other ending — one implementation, not two.

**This is the only path that cancels anything automatically.** The § 312k
BGB Kündigungsbutton (``app/routes/cancellation.py``, backend#372) is
login-free by law and therefore records a declaration and hands it to
support instead — an unauthenticated claim on an email address is not
evidence of who is asking. Here ``require_team_admin`` establishes identity
and authority together, which is what makes acting immediately safe.

## Response `200`

Successful Response

- object

---

[API](https://skmtc.dev/kernelscan/apis/kernelscan-api.md) · [All operations](https://skmtc.dev/kernelscan/apis/kernelscan-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kernelscan/apis/kernelscan-api/revisions/4fa51d41484e?raw)
