Skip to content
Hardcount
Run it locally
Pre-1.0 · one maintainer · Stripe and cards only · no SDKs (client libraries) yet · no production users yet. Docs describe v0.9.1 (29 Oct 2026) · What’s new →

Advance the clock to a new frozen_time

POST
/v1/test-clocks/{id}/advance
curl --request POST \
--url http://localhost:8080/v1/test-clocks/example/advance \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "frozen_time": "2026-04-15T12:00:00Z" }'

Moves the clock forward and runs billing catchup asynchronously for every subscription pinned to this clock. The 200 returns as soon as the clock is marked advancing — a background worker drains the catchup; poll GET /v1/test-clocks/{id} until status leaves advancing. Concurrent advances 409 while catchup runs. Catchup failures park the clock in internal_failure — resume it with POST /v1/test-clocks/{id}/retry-advance (deletion is not required). ADR-018. Catchup bills every skipped period before it runs payment retries and dunning, so when a dunning policy cancels or pauses a subscription, advance to the time of the invoice’s last retry first, then to the next billing date. The cancel or pause is dated at the advance target, and one longer advance bills a period a real clock would not (#1276).

id
required
string
Idempotency-Key
string

Makes the call safe to retry. Send a unique value (a UUID works) and the same value on every retry. For 24 hours, a repeat with the same key, method, path and body gets the first response again, with an Idempotent-Replayed: true header, instead of running again. The error cases are in docs/api-surface.md. The usage routes do not take it: each usage event carries its own idempotency_key.

Media typeapplication/json
object
frozen_time
required
string format: date-time

Example generated

{
"frozen_time": "2026-04-15T12:00:00Z"
}

Advance accepted — clock returned in advancing state

Media typeapplication/json

A clock for test mode. Customers and subscriptions attached to it are billed on its time, not the real time.

object
id
required
string
tenant_id
string
name
required
string
frozen_time
required

The clock’s current time.

string format: date-time
status
required

ready: it can be advanced or deleted. advancing: billing is catching up to the new time. internal_failure: the last advance failed partway; resume it with POST /v1/test-clocks/{id}/retry-advance.

string
Allowed values: ready advancing internal_failure
created_at
required
string format: date-time
updated_at
required
string format: date-time
last_failure_reason

Why the last advance failed. Cleared by the next successful advance.

string
last_advance_summary

What the latest advance did: the time span it covered and how many of each billing step it ran. Absent until the clock is first advanced.

object
advanced_from
required
string format: date-time
advanced_to
required
string format: date-time
invoices_generated
required
integer
trials_activated
required
integer
pauses_resumed
required
integer
thresholds_fired
required
integer
tax_retried
required
integer
charges_retried
required
integer
clawbacks_issued
required
integer
credits_expired
required
integer
dunning_advanced
required
integer
had_errors
required

True when a step failed. The counts then cover only the work done before the failure.

boolean

Example

{
"status": "ready"
}

Clock is not in ready state

New frozen_time is not strictly after the current frozen_time, or is more than one year after it