TillsafeDocstillsafe.comRequest early access

Subscriptions

Plans, customers and invoice-based recurring billing: renewal invoices, reminders, retries, prepaid credit

GET /v1/customers

List customers, newest first.

Authentication: Secret key

Parameters

ParameterInTypeDescription
limitqueryinteger (int32)

1 to 100, default 10

  • Minimum: 0
cursorquerystring

next_cursor from the previous page

Responses

StatusDescriptionBody
200
CustomerList application/json
400
ErrorResponse application/json

POST /v1/customers

Create a customer.

The email is optional and receives renewal reminders written in your display name. It is stored encrypted and only ever used for this customer's subscriptions.

Authentication: Secret key

Parameters

ParameterInTypeDescription
Idempotency-Keyrequiredheaderstring

Unique per customer

Request body

application/json

CreateCustomerRequest

FieldTypeDescription
namestring or null
emailstring or null

Where renewal reminders go. Optional: without it, you tell the customer yourself (the subscription.invoice_created webhook carries each invoice).

metadatamap of string or null

Responses

StatusDescriptionBody
201

Created

Customer application/json
400
ErrorResponse application/json

GET /v1/customers/{id}

Retrieve a customer, with their prepaid credit.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Customer id (cus_…)

Responses

StatusDescriptionBody
200
Customer application/json
404
ErrorResponse application/json

POST /v1/customers/{id}/top_up

Top up a customer's prepaid credit.

Creates an ordinary invoice for the customer. Once its payment is final, everything received becomes prepaid credit (in the tokens that arrived), and the next renewals consume it before invoicing.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Customer id (cus_…)

Idempotency-Keyrequiredheaderstring

Unique per top-up

Request body

application/json

TopUpRequest

FieldTypeDescription
amountrequiredstring
  • Example: "30.00"
currencyrequiredstring
  • Example: "USD"
assetsarray of string or null

Responses

StatusDescriptionBody
201

The top-up invoice

Invoice application/json
400
ErrorResponse application/json
404
ErrorResponse application/json

GET /v1/plans

List plans, newest first.

Authentication: Secret key

Parameters

ParameterInTypeDescription
limitqueryinteger (int32)

1 to 100, default 10

  • Minimum: 0
cursorquerystring

next_cursor from the previous page

Responses

StatusDescriptionBody
200
PlanList application/json
400
ErrorResponse application/json

POST /v1/plans

Create a plan.

A price per period and the period's length, plus the trial, the grace period before past_due, and how many payment attempts a period gets before the subscription is cancelled. Periods are counted in billing_timezone: a plan billed from the 31st renews on the last day of shorter months.

Authentication: Secret key

Parameters

ParameterInTypeDescription
Idempotency-Keyrequiredheaderstring

Unique per plan

Request body

application/json

CreatePlanRequest

FieldTypeDescription
namerequiredstring
  • Example: "VIP rank, monthly"
amountrequiredstring

Price per period, a decimal string.

  • Example: "9.99"
currencyrequiredstring
  • Example: "USD"
intervalrequiredIntervalUnit
interval_countinteger (int32) or null

Default 1. At most 365 days, 52 weeks, 12 months or 1 year.

  • Minimum: 0
trial_daysinteger (int32) or null

Default 0, at most 365.

  • Minimum: 0
grace_daysinteger (int32) or null

Default 3, at most 30.

  • Minimum: 0
max_attemptsinteger (int32) or null

Default 4, 1 to 7.

  • Minimum: 0
assetsarray of string or null
billing_timezonestring or null

IANA name, default UTC.

  • Example: "Europe/Berlin"

Responses

StatusDescriptionBody
201

Created

Plan application/json
400
ErrorResponse application/json

GET /v1/plans/{id}

Retrieve a plan.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Plan id (plan_…)

Responses

StatusDescriptionBody
200
Plan application/json
404
ErrorResponse application/json

POST /v1/plans/{id}/archive

Archive a plan: it takes no new subscriptions, and existing ones keep renewing.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Plan id (plan_…)

Idempotency-Keyrequiredheaderstring

Unique per request

Responses

StatusDescriptionBody
200
Plan application/json
404
ErrorResponse application/json

GET /v1/subscriptions

List subscriptions, newest first.

Authentication: Secret key

Parameters

ParameterInTypeDescription
limitqueryinteger (int32)

1 to 100, default 10

  • Minimum: 0
cursorquerystring

next_cursor from the previous page

statusquerySubscriptionStatus

Only subscriptions in this status

customerquerystring

Only this customer's (cus_…)

Responses

StatusDescriptionBody
200
SubscriptionList application/json
400
ErrorResponse application/json

POST /v1/subscriptions

Subscribe a customer to a plan.

With a trial, the subscription is active and the first renewal invoice comes one day before the trial ends. Without one, it is incomplete and the first invoice is created at once (the subscription.invoice_created webhook carries it, and the customer's email gets the payment link). Prepaid credit pays first.

Authentication: Secret key

Parameters

ParameterInTypeDescription
Idempotency-Keyrequiredheaderstring

Unique per subscription

Request body

application/json

CreateSubscriptionRequest

FieldTypeDescription
customerrequiredstring

cus_…

planrequiredstring

plan_… (must be active).

trial_daysinteger (int32) or null

Overrides the plan's trial (0 = start billing now).

  • Minimum: 0
metadatamap of string or null

Responses

StatusDescriptionBody
201

Created

Subscription application/json
400
ErrorResponse application/json
409

The plan is archived

ErrorResponse application/json

GET /v1/subscriptions/{id}

Retrieve a subscription.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Subscription id (sub_…)

Responses

StatusDescriptionBody
200
Subscription application/json
404
ErrorResponse application/json

POST /v1/subscriptions/{id}/cancel

Cancel a subscription, now or at the end of the paid period.

The body is optional ({} = cancel now). Cancelling now also cancels the open renewal invoice when nothing was paid on it, and returns prepaid credit that invoice had set aside. Repeating a cancel returns the subscription unchanged.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Subscription id (sub_…)

Idempotency-Keyrequiredheaderstring

Unique per request

Request body (optional)

Optional

application/json

CancelSubscriptionRequest or null

Responses

StatusDescriptionBody
200
Subscription application/json
404
ErrorResponse application/json
409

Already cancelled with another mode, or incomplete (nothing paid to keep)

ErrorResponse application/json

POST /v1/subscriptions/{id}/pause

Pause a subscription: no invoices and no reminders until it is resumed. An open renewal invoice with nothing paid is cancelled.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Subscription id (sub_…)

Idempotency-Keyrequiredheaderstring

Unique per request

Responses

StatusDescriptionBody
200
Subscription application/json
404
ErrorResponse application/json
409

Not active or past due

ErrorResponse application/json

POST /v1/subscriptions/{id}/resume

Resume a paused subscription. Inside a paid period it simply continues; after it, billing restarts now with a new period (and a new invoice). Resuming a subscription that is not paused (active, past due or incomplete) changes nothing and returns it.

Authentication: Secret key

Parameters

ParameterInTypeDescription
idrequiredpathstring

Subscription id (sub_…)

Idempotency-Keyrequiredheaderstring

Unique per request

Responses

StatusDescriptionBody
200
Subscription application/json
404
ErrorResponse application/json
409

The subscription is cancelled

ErrorResponse application/json