Countdown timer types

There are four types, and the choice matters more than anything else you send at creation. The type decides which timing field is required, whether a timezone means anything, whether the timer can be paused, and what happens when it reaches zero. It is fixed for the life of the timer — you cannot convert one type into another later.

Choosing in one question

Ask what the deadline is anchored to. That single question resolves the choice in almost every case.

If the deadline is…TypeRequired field
The same instant for everyonefixeddeadline_at
Elapsed time from when you start itdurationduration_seconds
A wall-clock time that comes round againrecurringrecurrence
Different for each individual personpersonalizedduration_seconds + external_user_id
If two of these sound right, you probably want two timers. A product launch that also runs a per-visitor discount window is a fixed countdown on the launch date and a personalized countdown per customer — not one timer trying to be both.

Fixed-date countdown

One exact deadline, shared by everyone who sees it. This is the sale that ends at midnight, the webinar that starts at 14:00, the auction that closes on the hour. Every viewer sees the same number of seconds remaining because they are all counting toward the same instant.

Create

{
  "name": "Black Friday sale ends",
  "type": "fixed",
  "deadline_at": "2030-11-29T23:59:59-05:00",
  "timezone": "America/New_York"
}

Worth knowing

  • deadline_at must carry Z or a numeric offset. A bare local timestamp is rejected.
  • timezone does not move the deadline — it records the zone the timer is displayed and edited in.
  • Cannot be paused. Change the deadline instead.
  • Moving the deadline is a normal update and costs nothing.

Duration timer

Elapsed time, not a calendar date. A duration timer starts at a number of seconds and counts toward zero, and unlike the other three it can be controlled: started, paused, resumed, and reset. Use it when the clock should begin at a moment you decide, not at a moment on the calendar.

Create

{
  "name": "Checkout reservation",
  "type": "duration",
  "duration_seconds": 900
}

Worth knowing

  • Minimum 1 second, maximum 31,536,000 — one year.
  • A new duration timer is idle. It does not count down until you send start.
  • Timezone is irrelevant and unused — elapsed time is elapsed time everywhere.
  • Pausing freezes remaining time; resuming continues from there rather than recomputing.
Cart holds, checkout reservations, exam windows, and gym intervals are all duration timers. The tell is that the deadline depends on when the user arrived, and you need to be able to stop it. Control them through the actions endpoint.

Recurring countdown

A schedule rather than a single deadline. The timer counts down to the next occurrence, and when that occurrence passes it rolls forward to the one after it — indefinitely, without you recreating anything.

Create

{
  "name": "Daily standup",
  "type": "recurring",
  "recurrence": {
    "frequency": "daily",
    "local_time": "09:30"
  },
  "timezone": "Europe/London"
}

Worth knowing

  • frequency and local_time are always required. Weekly adds days_of_week, monthly adds day_of_month, custom adds an rrule.
  • This is the one type where timezone changes behaviour: occurrences are computed in that zone, so 09:30 stays 09:30 across a DST shift.
  • Omitting the timezone runs the schedule in UTC, which is rarely what you want.
  • A completed cycle emits timer.recurrence_completed.

Schedule construction has enough detail to deserve its own page — recurring timers covers each frequency, the supported RRULE subset, and how cycles interact with webhook rules.

Personalized countdown

One timer definition, a separate deadline per person. You supply an external_user_id — your identifier for the recipient — and the deadline is fixed for that identity at the moment the timer is created. Two customers who sign up a day apart get windows that end a day apart.

Create

{
  "name": "Trial ends",
  "type": "personalized",
  "duration_seconds": 1209600,
  "external_user_id": "customer_8f21c"
}

Worth knowing

  • Needs both duration_seconds and external_user_id (1–255 characters).
  • The deadline is fixed at creation. It does not restart when the person returns.
  • The identifier is yours — a user ID, a hashed email, a CRM record. Use something stable.
  • Timezone is unused, for the same reason as duration timers.
This is the evergreen-deadline pattern, and it is the type most competitors cannot offer through an API at all. Trial expiry, per-recipient email offers, onboarding windows, and affiliate promotions all land here. See personalized timers.

Type is not status

Three separate ideas get confused constantly, so it is worth naming them side by side.

ConceptValuesWhere it comes from
Typefixed · duration · recurring · personalizedSet at creation. Permanent.
Statusdraft · published · archivedWhether the timer is publicly visible.
Live statescheduled · running · paused · endedComputed now, from GET /timers/{id}/status.

A published fixed countdown that has passed its deadline is status: "published" and state: "ended" at the same time, and both are correct. Read the live state from the status endpoint, not from the timer object.

What each type supports

FixedDurationRecurringPersonalized
Timezone affects behaviourNoNoYesNo
Start / pause / resume / resetNoYesNoNo
Repeats automaticallyNoNoYesNo
Deadline differs per viewerNoNoNoYes
Hosted page and embedsYesYesYesYes
Webhook rulesYesYesYesYes
Every type uses the same endpoints, counts against the same monthly allowance, and produces the same output formats. Choosing a type constrains the timing model, not the feature set.