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… | Type | Required field |
|---|---|---|
| The same instant for everyone | fixed | deadline_at |
| Elapsed time from when you start it | duration | duration_seconds |
| A wall-clock time that comes round again | recurring | recurrence |
| Different for each individual person | personalized | duration_seconds + external_user_id |
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_atmust carryZor a numeric offset. A bare local timestamp is rejected.timezonedoes 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.
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
frequencyandlocal_timeare always required. Weekly addsdays_of_week, monthly addsday_of_month, custom adds anrrule.- This is the one type where
timezonechanges 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_secondsandexternal_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.
Type is not status
Three separate ideas get confused constantly, so it is worth naming them side by side.
| Concept | Values | Where it comes from |
|---|---|---|
| Type | fixed · duration · recurring · personalized | Set at creation. Permanent. |
| Status | draft · published · archived | Whether the timer is publicly visible. |
| Live state | scheduled · running · paused · ended | Computed 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
| Fixed | Duration | Recurring | Personalized | |
|---|---|---|---|---|
| Timezone affects behaviour | No | No | Yes | No |
| Start / pause / resume / reset | No | Yes | No | No |
| Repeats automatically | No | No | Yes | No |
| Deadline differs per viewer | No | No | No | Yes |
| Hosted page and embeds | Yes | Yes | Yes | Yes |
| Webhook rules | Yes | Yes | Yes | Yes |