Countdown Timer API endpoint reference

Every route in the API, what it does, and what it costs you. All paths are relative to https://countdownshare.com/api/v1 and every response is JSON. If you want the machine-readable version instead, the OpenAPI 3.1 spec is public and needs no key.

Timers

The core resource. Sixteen routes, of which you will use three or four in a typical integration.

MethodEndpointPurpose
GET/timersList timers, filtered by type and status
POST/timersCreate a timer — requires Idempotency-Key
GET/timers/{timer_id}Get one timer and its publication status
PATCH/timers/{timer_id}Update a timer — requires If-Match
DELETE/timers/{timer_id}Delete permanently
POST/timers/{timer_id}/duplicateCopy a timer — requires Idempotency-Key
POST/timers/{timer_id}/archiveMove out of the active set
POST/timers/{timer_id}/restoreBring an archived timer back
POST/timers/{timer_id}/actionsStart, pause, resume, or reset a duration timer
GET/timers/{timer_id}/statusRead live status and remaining time
GET/timers/{timer_id}/outputsGet hosted page, embed, and email GIF URLs
GET/timers/{timer_id}/activityPaginated history of changes and actions
GET/timers/{timer_id}/metricsViews, unique visitors, interactions, conversions

Webhooks

Destinations are account-level and reusable. Rules live under the timer they watch. Deliveries are the record of what we actually sent.

MethodEndpointPurpose
GET/webhook-destinationsList destinations
POST/webhook-destinationsRegister a destination — returns the signing secret once
GET/webhook-destinations/{destination_id}Get one destination, without its secret
PATCH/webhook-destinations/{destination_id}Change name, URL, description, or enabled state
DELETE/webhook-destinations/{destination_id}Delete a destination no rule depends on
POST/webhook-destinations/{destination_id}/testSend a signed test delivery
POST/webhook-destinations/{destination_id}/rotate-secretReplace the signing secret
GET/timers/{timer_id}/webhook-rulesList rules on a timer
POST/timers/{timer_id}/webhook-rulesAttach a rule to a timer
PATCH/timers/{timer_id}/webhook-rules/{rule_id}Change a condition, destination, or state
DELETE/timers/{timer_id}/webhook-rules/{rule_id}Remove a rule
GET/webhook-deliveriesList deliveries, filterable by status
GET/webhook-deliveries/{delivery_id}Get one delivery with its attempt history
POST/webhook-deliveries/{delivery_id}/replayReplay a delivery for the same event

Account and reference

MethodEndpointPurpose
GET/timezonesList accepted IANA timezone identifiers
GET/usageCurrent plan usage, limits, and cycle dates
GET/usage/requestsYour API request log
GET /usage is the cheapest way to confirm a key works and to see which environment it belongs to. It creates nothing and returns immediately.

What counts against your allowance

Only creation is metered. Requests are not the billing unit — there is no monthly cap on API calls on any plan, just a per-minute rate limit.

Consumes a timer

  • POST /timers
  • POST /timers/{timer_id}/duplicate

Free, unlimited

Everything else. Reading status, updating a deadline, pausing, archiving, restoring, deleting, attaching rules, and reading metrics all cost nothing beyond a request against the per-minute limit.

This shapes the design of a good integration: create one timer per real-world thing and then update it, rather than deleting and recreating. Moving a deadline is free; recreating the timer to move it is not. Full detail on the pricing page.

Routes with extra header requirements

Beyond Authorization on everything and Content-Type on bodies, three routes require one more header — and reject the request without it.

RouteHeaderValue
POST /timersIdempotency-KeyAny stable string, 1–255 characters
POST /timers/{id}/duplicateIdempotency-KeyAny stable string, 1–255 characters
PATCH /timers/{id}If-MatchThe timer's current revision, as an integer

The timer object

What GET /timers/{timer_id} returns under data. Fields that do not apply to a timer's type are null rather than absent, so the shape is stable across all four types.

200 OK — a published fixed countdown

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Product launch",
  "type": "fixed",
  "status": "published",
  "revision": 3,
  "deadline_at": "2030-01-01T14:00:00.000Z",
  "duration_seconds": null,
  "remaining_seconds": 2692800,
  "timezone": "America/New_York",
  "recurrence": null,
  "external_user_id": null,
  "expiry": { "behavior": "show_message", "message": "This offer has closed" },
  "metadata": { "campaign_id": "q1-launch" },
  "outputs": {
    "public_page_url": "https://countdownshare.com/api/c/550e8400-...",
    "website_embed_html": "<iframe ...></iframe>",
    "email_embed_html": "<a href=\"...\"><img src=\"...\"></a>",
    "json_data_url": "https://countdownshare.com/api/v1/timers/550e8400-.../status"
  },
  "created_at": "2029-12-01T10:00:00.000Z",
  "updated_at": "2029-12-14T08:31:22.000Z"
}

Field reference

FieldTypeNotes
iduuidImmutable. The identifier every other endpoint takes.
namestringYour internal label, 1–200 characters.
typeenumfixed · duration · recurring · personalized. Fixed at creation.
statusenumdraft · published · archived. Publication state, not the clock.
revisionintegerIncrements on every change. Send it in If-Match to update.
deadline_atstring | nullISO 8601 UTC. Non-null for fixed timers.
duration_secondsinteger | nullNon-null for duration and personalized timers.
remaining_secondsinteger | nullA snapshot at read time. Use /status for the live clock.
timezonestringIANA identifier. Defaults to UTC.
recurrenceobject | nullThe schedule, for recurring timers.
external_user_idstring | nullYour identifier, for personalized timers.
expiryobjectbehavior is show_message, hide, or redirect.
metadataobjectUp to 50 of your own key-value pairs, returned verbatim.
outputsobject | nullDisplay URLs. Null unless the timer is published in Production.
created_atstringISO 8601 UTC.
updated_atstringISO 8601 UTC.
remaining_seconds on the timer object is a convenience snapshot taken when you read it. For anything you render, call the status endpoint — it returns a broken-down remaining time and the server clock you should be counting against.