---
title: "Everything the cancellation flow UI needs in one read"
method: GET
path: "/api/cancellation/context"
tags: ["Cancellation"]
---

# Everything the cancellation flow UI needs in one read

`GET /api/cancellation/context`

## Request

- Base URL: `https://api.setluca.com`
- URL: `https://api.setluca.com/api/cancellation/context`
- Auth: API key in cookie `luca.session_token`

One read that renders the whole flow. It returns the plan, billing interval, and period end, what Luca has done for this coach, whether an open balance or a save cap turns offers off, any renewal-grace refund on the table, and the offers each reason leads with. The client never needs a second round trip to decide what to show.

**Session-only.** This endpoint isn't on the API-key allowlist. An organization API key gets a 403 here, whatever scopes it holds.

## Headers

- `Luca-API-Version` '1'

## Response `200`

ok

- CancellationContextResponse
  - `planTier` string, required
  - `billingInterval` 'month' | 'year', required
  - `planStatus` string, required
  - `trialOrPaid` 'trial' | 'paid', required
  - `periodEndsAt` string, nullable, required
  - `pausedUntil` string, nullable, required
  - `cancelRequested` boolean, required
  - `voiceMessageCount` integer, required
  - `leadsHandled` integer, required
  - `callsBooked` integer, required
  - `midConversationLeads` integer, required
  - `saveCapped` boolean, required
  - `pastDue` boolean, required
  - `graceRefund` object, required
    - `eligible` boolean, required
    - `amountCents` integer, required
  - `offersByReason` object, required
    - `too_expensive` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `not_enough_dms` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `voice_mismatch` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `missing_feature` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `switching` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `bugs` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `taking_break` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `just_testing` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
    - `other` CancellationReasonOffers
      - `primary` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `fallback` object, nullable, required
        - `kind` 'discount' | 'discount_once' | 'pause_1m' | 'pause_2m' | 'downgrade' | 'trial_extension' | 'pause' | 'founder_call' | 'voice_retraining' | 'roadmap_promise' | 'bug_escalation' | 'cancel_gracefully', required
        - `percentOff` integer
        - `months` integer
      - `skipped` 'capped' | 'past_due' | 'null', nullable, required
  - `founderCallUrl` string, nullable, required
  - `founderReplyEmail` string, required
  - `voiceRetentionDays` integer, required

## Other responses

- `401`: unauthorized
- `404`: not found
- `429`: rate limited
- `500`: internal error
- `503`: service unavailable

---

[API](https://skmtc.dev/setluca/apis/luca-api.md) · [All operations](https://skmtc.dev/setluca/apis/luca-api/llms.txt) · [OpenAPI document](https://skmtc.dev/setluca/apis/luca-api/revisions/90a200e4100b?raw)
