{
  "slug": "trial-ending-email-sequence",
  "title": "Trial ending email sequence: template and code",
  "url": "https://www.courier.com/recipes/trial-ending-email-sequence",
  "markdown": "https://www.courier.com/recipes/trial-ending-email-sequence.md",
  "stage": "Monetization",
  "purpose": "Remind trial users before their trial ends, and stop the moment they upgrade.",
  "summary": "A trial ending email sequence reminds users that their free trial is about to expire. It sends an email and an Inbox note 7 days before the trial ends, another a day before, with a text if the first email wasn't opened, and a final email when it ends. Upgrading stops the rest.",
  "channels": [
    "email",
    "inbox",
    "sms"
  ],
  "shape": "journey",
  "shows": [
    "Waits of 7 days, 6 days, then 1 day",
    "A condition on whether an earlier email was opened",
    "Cancel every run for a user with one call"
  ],
  "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": "trial_end_date",
      "type": "string",
      "example": "2026-10-29T17:00:00Z",
      "note": "An ISO timestamp. The templates format it as a date in the recipient's timezone"
    }
  ],
  "steps": [
    {
      "step": "1",
      "when": "7 days before the trial ends, after the journey's first wait",
      "channels": "Email, Inbox",
      "templates": [
        "templates/trial-7d-email.json",
        "templates/trial-7d-inbox.json"
      ]
    },
    {
      "step": "2",
      "when": "6 days after step 1, 1 day before the trial ends",
      "channels": "Email, Inbox. SMS too if step 1's email wasn't opened",
      "templates": [
        "templates/trial-1d-email.json",
        "templates/trial-1d-inbox.json",
        "templates/trial-1d-sms.json"
      ]
    },
    {
      "step": "3",
      "when": "1 day after step 2, when the trial ends",
      "channels": "Email",
      "templates": [
        "templates/trial-ended-email.json"
      ]
    }
  ],
  "files": {
    "journey": "journey.json",
    "templates": [
      "templates/trial-7d-email.json",
      "templates/trial-7d-inbox.json",
      "templates/trial-1d-email.json",
      "templates/trial-1d-inbox.json",
      "templates/trial-1d-sms.json",
      "templates/trial-ended-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/cancel",
    "https://www.courier.com/docs/journeys/invoke",
    "https://www.courier.com/docs/guides/notify-from-stripe"
  ],
  "related_recipes": [
    "https://www.courier.com/recipes/stalled-trial-slack-alert",
    "https://www.courier.com/recipes/dunning-email-sequence",
    "https://www.courier.com/recipes/subscription-renewal-reminder-email"
  ],
  "agent_prompt": "Add trial ending reminders to this app, sent through Courier: two reminders before a trial ends, a final note when it ends, and nothing more once the account upgrades. Follow the steps at https://www.courier.com/recipes/trial-ending-email-sequence.md and use the Courier skill for SDK details.\n\n1. Create the journey and its six 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_TRIAL_JOURNEY_ID. Replace the placeholder product name (Acme) and the billing link in the templates with ours, and if our trials aren't 14 days, set the journey's first wait to the trial length minus 7 days.\n2. Find where this codebase starts a trial 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 upgrades (usually the billing webhook) and cancel the journey with the token trial-<user ID>. When a trial is extended, cancel it and start it again.\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 run waits before its first reminder, so cancel the test run once you've checked it.",
  "status": {
    "state": "passing",
    "last_tested": "2026-10-19"
  }
}
