{
  "slug": "subscription-cancellation-email",
  "title": "Subscription cancellation email: template and code",
  "url": "https://www.courier.com/recipes/subscription-cancellation-email",
  "markdown": "https://www.courier.com/recipes/subscription-cancellation-email.md",
  "stage": "Retention",
  "purpose": "Confirm the cancellation, ask why, and make one good offer to come back.",
  "summary": "A subscription cancellation email sequence follows up after a customer cancels. It confirms the cancellation right away with the date their access ends, asks one feedback question a week later, and sends a single win-back offer after 30 days, all by email. Resubscribing stops anything that hasn't gone out.",
  "channels": [
    "email"
  ],
  "shape": "journey",
  "shows": [
    "One-click feedback links",
    "Waits of 7 days, then 23 more",
    "Cancel when they resubscribe"
  ],
  "data": [
    {
      "name": "profile.first_name",
      "type": "string",
      "example": "Dana",
      "note": "From the profile. \"there\" is the fallback when it's missing"
    },
    {
      "name": "plan_name",
      "type": "string",
      "example": "Pro"
    },
    {
      "name": "access_ends_at",
      "type": "string",
      "example": "2026-11-14T17:00:00Z",
      "note": "An ISO timestamp. The confirmation formats it as a date in the recipient's timezone"
    }
  ],
  "steps": [
    {
      "step": "1",
      "when": "Right after the customer cancels",
      "channels": "Email",
      "templates": [
        "templates/cancel-confirm-email.json"
      ]
    },
    {
      "step": "2",
      "when": "7 days after they cancel",
      "channels": "Email",
      "templates": [
        "templates/cancel-feedback-email.json"
      ]
    },
    {
      "step": "3",
      "when": "23 days after the feedback email, 30 days after they cancel",
      "channels": "Email",
      "templates": [
        "templates/winback-email.json"
      ]
    }
  ],
  "files": {
    "journey": "journey.json",
    "templates": [
      "templates/cancel-confirm-email.json",
      "templates/cancel-feedback-email.json",
      "templates/winback-email.json"
    ],
    "setup": [
      "setup.ts"
    ],
    "start": [
      "start.ts",
      "start.py"
    ],
    "stop": [
      "stop.ts",
      "stop.py"
    ]
  },
  "docs": [
    "https://www.courier.com/docs/journeys/nodes/delay",
    "https://www.courier.com/docs/journeys/nodes/send",
    "https://www.courier.com/docs/journeys/nodes/cancel",
    "https://www.courier.com/docs/journeys/invoke"
  ],
  "related_recipes": [
    "https://www.courier.com/recipes/win-back-email-sequence",
    "https://www.courier.com/recipes/nps-survey-email",
    "https://www.courier.com/recipes/dunning-email-sequence"
  ],
  "agent_prompt": "Add cancellation follow-up emails to this app, sent through Courier: a confirmation right away, a one-question feedback email after 7 days, and one offer to come back after 30 days. Follow the steps at https://www.courier.com/recipes/subscription-cancellation-email.md and use the Courier skill for SDK details.\n\n1. Create the journey and its templates in my Courier workspace by running setup.ts from that page with COURIER_API_KEY from our environment. Save the journey ID it prints as COURIER_CANCELLATION_JOURNEY_ID. Replace the placeholder product name (Acme), the app.acme.com links, and the offer (50% off) in the templates with ours.\n2. Find where a customer cancels a subscription and keeps access until the period ends (in Stripe, customer.subscription.updated when cancel_at_period_end changes to true, not customer.subscription.deleted, which fires when access actually ends) and start the journey there with the user's ID. Pass the fields in the Data fields table from our own data.\n3. Find where an account resubscribes, or undoes the cancellation (cancel_at_period_end back to false in Stripe), and cancel the journey with the token winback-<user ID>.\n4. Match this codebase's language, file layout, and error handling. Never hardcode the API key.\n5. When you're done, start one run for a test user and show me the run's steps. The confirmation sends right away and the run then waits 7 days, so cancel the test run once you've checked it.",
  "status": {
    "state": "passing",
    "last_tested": "2026-10-19"
  }
}
