{
  "slug": "email-verification-reminder-email",
  "title": "Email verification reminder email: template and code",
  "url": "https://www.courier.com/recipes/email-verification-reminder-email",
  "markdown": "https://www.courier.com/recipes/email-verification-reminder-email.md",
  "stage": "Onboarding",
  "purpose": "Get new signups to confirm their email, and stop reminding them the moment they do.",
  "summary": "An email verification reminder gets new signups to confirm their email address. It sends the verification email at signup, a reminder the next day, and a last notice on day 6, the day before unverified accounts are removed. Everything goes by email, and confirming the address stops the reminders.",
  "channels": [
    "email"
  ],
  "shape": "journey",
  "shows": [
    "Cancel the journey once the email is verified",
    "Waits set as durations, not dates",
    "A last notice the day before cleanup"
  ],
  "data": [
    {
      "name": "profile.first_name",
      "type": "string",
      "example": "Dana",
      "note": "From the profile. \"there\" is the fallback when it's missing"
    },
    {
      "name": "token",
      "type": "string",
      "example": "k3J9x",
      "note": "The verification token your app already issued, not the user ID. The templates build the link from it, so use URL-safe characters"
    }
  ],
  "steps": [
    {
      "step": "1",
      "when": "Right after signup",
      "channels": "Email",
      "templates": [
        "templates/verify-email.json"
      ]
    },
    {
      "step": "2",
      "when": "1 day after signup",
      "channels": "Email",
      "templates": [
        "templates/verify-reminder-email.json"
      ]
    },
    {
      "step": "3",
      "when": "6 days after signup, the day before a 7-day cleanup",
      "channels": "Email",
      "templates": [
        "templates/verify-final-email.json"
      ]
    }
  ],
  "files": {
    "journey": "journey.json",
    "templates": [
      "templates/verify-email.json",
      "templates/verify-reminder-email.json",
      "templates/verify-final-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",
    "https://www.courier.com/docs/guides/build-an-onboarding-sequence"
  ],
  "related_recipes": [
    "https://www.courier.com/recipes/welcome-email-sequence",
    "https://www.courier.com/recipes/magic-link-email",
    "https://www.courier.com/recipes/password-reset-email"
  ],
  "agent_prompt": "Add email verification reminders to this app, sent through Courier: a verification email at signup, a reminder a day later, and a last notice the day before we clean up unverified accounts, all skipped once the email is verified. Follow the steps at https://www.courier.com/recipes/email-verification-reminder-email.md and use the Courier skill for SDK details.\n\n1. Create the journey and its templates in my Courier workspace by replacing Acme and the verification link in the template files with our own, then running setup.ts from that page with COURIER_API_KEY from our environment. The last notice goes on day 6, so if we remove unverified accounts after something other than 7 days, change the second wait in journey.json first. Save the journey ID it prints as COURIER_VERIFY_JOURNEY_ID.\n2. Find where this codebase creates a new user and issues their email verification token, and start the journey there. Pass the fields in the Data fields table: token is the verification token we already issue, never the user ID. Replace the base URL in the templates with our verification page.\n3. Find where an email address gets verified and cancel the journey there with the token verify-<user_id>. Cancel it the same way when an account is deleted.\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.",
  "status": {
    "state": "passing",
    "last_tested": "2026-10-19"
  }
}
