> ## Documentation Index
> Fetch the complete documentation index at: https://docs.minimo.it/llms.txt
> Use this file to discover all available pages before exploring further.

# Reminders before a date

> Send a message N hours or days before (or after) a date of the contact: events, appointments, bookings, renewals, expiries.

## Overview

A reminder before a date is a normal automation, no custom code needed:

1. a **trigger** that fires when the contact gets the date (a registration, a booking, a field update),
2. a **wait until a moment relative to a date field** of the contact ("6 hours before", "1 day before", "3 days after"),
3. the **message**.

Chain more waits and messages for more reminders, for example 6 hours and 1 hour before an event.

The date is read from a contact field when the wait starts. It can be a regular field (`appointment_at`, `trial_ends_at`) or a [dynamic field](https://docs.minimo.it/product/data-sync/dynamic-fields.md) computed from your connected database, such as the start of the next tournament a player registered to.

## Example: tournament reminders (6 hours and 1 hour before)

A tournament app stores tournaments in `tornei` (with the start time in `tornei.inizio`) and registrations in `tornei_iscritti` (`utente_id`, `compagno_id`). The goal: every registered player gets a reminder 6 hours before the start and another one 1 hour before.

**1. Give each player the date**

Create a dynamic field with **Ask Mo**:

> Create a dynamic field NEXT\_TOURNAMENT\_START (datetime): for each contact, the minimum of `tornei.inizio` across the tournaments in `tornei_iscritti` where the person is `utente_id` or `compagno_id`, with a start date in the future.

The field is filled for every player right away and recomputed when a registration is added or changes.

**2. Build the automation**

Describe it to Mo (or to Claude through the Minimo MCP):

> When NEXT\_TOURNAMENT\_START is updated, wait until 6 hours before NEXT\_TOURNAMENT\_START and send a reminder email, then wait until 1 hour before and send a last-call email.

Mo creates it as a draft:

* **Trigger:** Field updated, `NEXT_TOURNAMENT_START`
* **Wait:** until 6 hours before `NEXT_TOURNAMENT_START`, skip the next step if the moment has passed
* **Email:** "The tournament starts in 6 hours"
* **Wait:** until 1 hour before `NEXT_TOURNAMENT_START`, skip the next step if the moment has passed
* **Email:** "Last call: the tournament starts in 1 hour"

**3. Review and activate**

Open the draft in the builder, check the copy and activate it. If your app already sends these reminders from code, turn that code path off when the automation goes live, so players don't get them twice.

## Build it by hand

In the builder add a **Delay** step and choose **Based on a contact date**:

* **Contact date field:** any field of type date or datetime (fields synced from your database included).
* **When:** *Before*, *After* or *On the exact date*, with an offset in minutes, hours or days.
* **Skip the next step if this moment has already passed:** see below.

## Late registrations

If someone registers 3 hours before the start, "6 hours before" is already in the past.

* With **Skip the next step if this moment has already passed** on, the wait does not hold the contact and the step right after it (the 6-hour reminder) is skipped. The flow goes on, so the 1-hour reminder still goes out on time.
* With it off, the wait ends immediately and the next step runs right away (the 6-hour reminder is sent late).

Automations created by Mo turn it on. For waits you add by hand it is off unless you switch it on.

If the contact has no value in the date field (or the value is not a date), the run stops at the wait and nothing after it is sent.

> [!NOTE]
>
> The skip option and the stop on a missing date are delivered by the latest automation engine release, which is rolling out now. Until it is live, a wait whose moment has already passed ends immediately and the reminder goes out right away instead of being skipped.

## Good to know

* **One date per contact.** A wait reads one value. With a dynamic field like "next tournament start", a player registered to several tournaments is reminded for the nearest one; the next one gets its reminders when the field moves to it.
* **A new-row trigger does not carry the row.** A trigger on a new row in a synced table starts the flow for the matched contact, but the row's own values do not reach the steps today. Read the date from a contact field instead: a dynamic field such as the next tournament start, a Field updated trigger and a wait until N hours before, exactly the pattern above.
* **The date is read when the wait starts.** Each wait reads the field at that moment, so a second wait uses the current value.
* **Time zones.** Store dates with their time zone (for example a Postgres `timestamptz`). The reminder fires at that exact instant.
* **Recompute on data changes.** A dynamic field is recomputed when its data changes, not only because time passed. See [Dynamic fields](https://docs.minimo.it/product/data-sync/dynamic-fields.md).

> [!TIP]
>
> Other uses of the same pattern: appointment reminders (1 day and 2 hours before `appointment_at`), renewal notices (7 days before `renews_at`), trial endings (3 days before `trial_ends_at`), follow-ups after an event (1 day after `event_end`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.