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 →

Clear a scheduled cancel

DELETE
/v1/subscriptions/{id}/scheduled-cancel
curl --request DELETE \
--url http://localhost:8080/v1/subscriptions/example/scheduled-cancel \
--header 'Authorization: Bearer <token>'

Removes a scheduled cancel and sends the subscription.cancel_cleared webhook event. Calling it on a subscription with no schedule returns the subscription unchanged and sends no event.

If the scheduled date has already passed, the cancel has taken effect and the request answers 409.

id
required
string

The subscription with no scheduled cancel.

Media typeapplication/json
object
id
required
string
tenant_id
string
code
required
string
display_name
required
string
customer_id
required
string
items

The subscription’s priced lines. Each item names its plan.

Array<object>

One priced line of a subscription. It pairs a plan with a quantity.

object
id
required
string
tenant_id
string
subscription_id
required
string
plan_id
required
string
quantity
required
integer format: int64
metadata

The item’s stored metadata. Absent when empty.

object
key
additional properties
any
pending_plan_id

Plan the item moves to at pending_plan_effective_at. Absent when no change is scheduled.

string
pending_plan_effective_at
string format: date-time
plan_changed_at

When the plan was last changed immediately. Absent until the first such change.

string format: date-time
created_at
required
string format: date-time
updated_at
required
string format: date-time
status
required
string
Allowed values: draft trialing active canceled
billing_time
required
string
Allowed values: calendar anniversary
trial_start_at
string format: date-time
trial_end_at
string format: date-time
started_at
string format: date-time
activated_at
string format: date-time
canceled_at

When the subscription was canceled. Absent until then.

string format: date-time
cancel_at

A scheduled cancel time, if one is set.

string format: date-time
cancel_at_period_end
required

True when the subscription cancels at the end of the current period.

boolean
cancel_effective_at

When a scheduled cancel takes effect. Absent when no cancel is scheduled.

string format: date-time
pause_collection

Present on a subscription while collection is paused. New invoices are still created, but stay drafts and are not charged.

object
behavior
required
string
Allowed values: keep_as_draft
resumes_at

When collection resumes. Absent when the pause lasts until it is cleared. On a pause set by dunning, it is when Hardcount recorded the payment of the invoice the pause was set for.

string format: date-time
set_by
required

Who paused collection. operator: you, through the API or the dashboard; the pause lasts until you resume it or until resumes_at. dunning: a dunning policy’s pause final action. A dunning pause lifts by itself once the invoice whose dunning set it is paid, even if another invoice is still owed. Periods that ended during the pause keep their draft invoices.

string
Allowed values: operator dunning
billing_thresholds

Limits that make Hardcount invoice before the period ends. A threshold invoice bills the period’s usage so far, and no base fee. The period keeps its dates, the base fee is billed as it would be with no threshold, and the period’s next invoice bills the rest of the usage.

object
amount_gte

Usage threshold in cents, compared with the period’s usage so far (the base fee is not counted). Absent when not set.

integer format: int64
item_thresholds
required
Array<object>
object
subscription_item_id
required
string
usage_gte
required

Usage quantity threshold, as a decimal string.

string
current_billing_period_start
string format: date-time
current_billing_period_end

End of the current period (exclusive).

string format: date-time
current_billing_period_display

The current period as text, with the last day included, in the tenant’s billing time zone.

string
next_billing_at
string format: date-time
billing_anchor_day

Day of the month the subscription bills on (1-31). Absent for calendar-monthly subscriptions.

integer
test_clock_id
string
billing_failure

Present on a subscription while the billing run is failing on the work that subscription has due now (a period close, or a scheduled mid-period cancel). Absent otherwise: a subscription that bills cleanly, or whose due work changed, carries no billing_failure.

After each failed attempt the billing run waits before the next one: 15 minutes, 1 hour, 4 hours, 12 hours, then 24 hours three times. The eighth failure parks the subscription (parked: true, no next_attempt_at). A parked subscription is not attempted again until POST /v1/subscriptions/{id}/retry-billing is called.

Never set on a subscription attached to a test clock.

object
attempts
required

Failed attempts on the work that is due now. At least 1.

integer
max_attempts
required

The attempt at which the subscription parks (8).

integer
last_error
required

Why the latest attempt failed: a sentence an operator can act on, or a generic line carrying the subscription id as the reference to search the server log for. Never raw error text.

string
failed_at
required

When the latest attempt failed.

string format: date-time
next_attempt_at

The billing run does not attempt the subscription before this instant. The attempt happens on the first run at or after it, so on an hourly schedule it can be up to an hour later. Absent when parked.

string format: date-time
parked
required

True when automatic attempts have stopped.

boolean
created_at
required
string format: date-time
updated_at
required
string format: date-time

Example

{
"status": "draft",
"billing_time": "calendar",
"pause_collection": {
"behavior": "keep_as_draft",
"set_by": "operator"
}
}

Subscription not found.

Media typeapplication/json
object
error
object
type

One of invalid_request_error, authentication_error, rate_limit_error or api_error. Every error the API answers has this shape, including an unknown path (404, code route_not_found) and a method the path does not take (405, code method_not_allowed, with an Allow header). The few exceptions are listed in docs/api-surface.md.

string
code
string
message
string
request_id
string
param

The request field the error is about. Sent only when the error names one. A request body may hold only the fields its operation lists, spelled and cased as listed: any other field, or one the server sets (such as id), is refused with 422 and param naming it. An operation with no request body lists no fields: send no body, {} or null. The Stripe and Postmark webhooks and the LiteLLM callback take their sender’s body as it comes.

string

Example

{
"error": {
"type": "invalid_request_error"
}
}

Code invalid_state: the scheduled cancel already took effect when the billing period ended. Code unbilled_period: a billing period ended and could not be invoiced; retry billing first.

Media typeapplication/json
object
error
object
type

One of invalid_request_error, authentication_error, rate_limit_error or api_error. Every error the API answers has this shape, including an unknown path (404, code route_not_found) and a method the path does not take (405, code method_not_allowed, with an Allow header). The few exceptions are listed in docs/api-surface.md.

string
code
string
message
string
request_id
string
param

The request field the error is about. Sent only when the error names one. A request body may hold only the fields its operation lists, spelled and cased as listed: any other field, or one the server sets (such as id), is refused with 422 and param naming it. An operation with no request body lists no fields: send no body, {} or null. The Stripe and Postmark webhooks and the LiteLLM callback take their sender’s body as it comes.

string

Example

{
"error": {
"type": "invalid_request_error"
}
}