Subscription schedules
Use subscription schedules for advanced billing timelines where a normal Checkout-created or directly created subscription is not enough.
Schedules are not required for most first integrations. Start with Create subscriptions with Checkout when the customer needs to enter payment details, and use Create subscriptions directly when your backend already has a Customer and reusable payment method.
What this page is for
This page explains how schedules work when you need:
- a subscription that starts in the future;
- planned phase changes;
- intro pricing followed by standard pricing;
- a fixed-duration subscription timeline;
- a backend-owned billing plan that should run without manual phase updates.
When to use schedules
Use a schedule when the billing plan needs a timeline.
Common uses:
| Use case | Why a schedule helps |
|---|---|
| Future start | Create the schedule now and let Paypercut create the subscription when the first phase starts. |
| Multi-phase billing | Define each phase upfront so Paypercut applies the changes automatically. |
| Intro pricing | Start with a lower recurring amount, then move to the standard recurring amount in a later phase. |
| Fixed-duration billing | End or release the subscription after the final phase, depending on end_behavior. |
| Delayed billing or trials | Use phase dates and trial_end when billing should not begin immediately. |
When not to use schedules
Do not use schedules when:
- you only need a simple recurring plan;
- the customer still needs to enter or confirm payment details;
- you have not configured webhook handling;
- you only need to change a subscription once right now;
- you are trying to use
send_invoice, which is currently rejected by backend validation.
Schedules add another object and another lifecycle. Use them only when the timeline matters.
Before you start
Prepare:
- A Paypercut Customer.
- A reusable payment method for that Customer.
- Recurring Price IDs or inline phase item data that matches the public API schema.
- A webhook endpoint that handles
invoice.paidandinvoice.payment_failed. - Database fields for both
schedule_idandsubscription_id.
Activation requires a default payment method in default_settings.default_payment_method. If the first phase is reached and no default payment method is available, the schedule cannot activate the subscription.
Key concepts
| Concept | Meaning |
|---|---|
| Schedule | The timeline object. It stores phases and controls when a subscription is created or updated. |
| Phase | A dated segment of the schedule. Each phase has a start_date and at least one recurring item. |
| First phase | The phase that creates the linked subscription when it starts. |
| Later phase | A phase that updates the linked subscription's items and settings. |
subscription |
Null until the schedule activates and creates or controls a subscription. |
next_action_at |
The next time the schedule workflow expects to activate a phase or finish the schedule. |
end_behavior |
What happens after the final phase: release, cancel, or no-op, depending on the configured value and verified behavior. |
Schedule object model
When you create a schedule, Paypercut creates the schedule object first.
The schedule response includes:
id;customer;status;phases;start_date;current_phase_index;current_phase;next_action_at;subscription;released_subscription;end_behavior.
Store the schedule ID immediately. Store the subscription ID later, after the schedule activates and the response or a later retrieve call includes subscription.
Phase model
Phases are applied in order.
Each phase has:
start_date;- optional
end_date; - optional
trial_end; - optional
billing_cycle_anchor; - optional
collection_method; - one or more
items.
Every phase must include at least one recurring item. Recurring items in the same phase must share the same interval and interval count.
When the first phase is applied, Paypercut creates the subscription from the phase items and default settings. When a later phase is applied, Paypercut updates the existing subscription with the phase items.
Actor ownership
| Actor | Owns |
|---|---|
| Your backend | Creates the schedule, stores IDs, retrieves schedule and subscription state, and handles invoice events. |
| Paypercut | Stores the schedule, applies phases, creates or updates the subscription, collects payment, and sends invoice events. |
| Customer | Already has a reusable payment method before the schedule activates. |
Common schedule patterns
| Pattern | How to model it | Access signal |
|---|---|---|
| Future start | First phase start_date is in the future. |
No paid access until the linked subscription exists and billing is confirmed. |
| Intro pricing | Phase 0 uses the intro recurring price; phase 1 uses the standard recurring price. | Use invoice.paid for the paid period after each billing event. |
| Fixed duration | Use multiple phases and end_behavior to control what happens after the final phase. |
Inspect the schedule and subscription after the final phase. |
| Trial or delayed billing | Set trial_end on the first phase when supported by your product policy. |
Trial access is your policy; paid access still comes from invoice events. |
Creating a schedule
Create schedules from your backend.
This example creates a future-start subscription schedule with one recurring phase. The schedule is created immediately, but the linked subscription is not created until the first phase starts.
curl https://api.paypercut.io/v1/subscription-schedules \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-subscription-schedule-01" \
-d '{
"customer": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"default_settings": {
"default_payment_method": "01HD7M6DRKZ4Q4QEVWJB0RC1S6"
},
"end_behavior": "RELEASE",
"phases": [
{
"start_date": "2026-08-01T00:00:00Z",
"items": [
{
"price": "01HFRECURRINGPRICE000000000",
"unit_amount": 2999,
"currency": "USD",
"recurring": {
"interval": "monthly",
"interval_count": 1
}
}
]
}
],
"metadata": {
"internal_account_id": "acct_123",
"plan": "pro_monthly"
}
}'
After this request:
- Store the returned schedule
id. - Do not expect a
subscriptionID until the first phase activates. - Do not grant paid access from schedule creation alone.
- Retrieve the schedule later to store the linked
subscriptionwhen it exists. - Use
invoice.paidto grant or extend paid access.
Intro pricing example
Use separate prices for intro and standard recurring amounts. The later phase replaces the subscription's items when the phase starts.
curl https://api.paypercut.io/v1/subscription-schedules \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-intro-schedule-01" \
-d '{
"customer": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"default_settings": {
"default_payment_method": "01HD7M6DRKZ4Q4QEVWJB0RC1S6"
},
"end_behavior": "RELEASE",
"phases": [
{
"start_date": "2026-08-01T00:00:00Z",
"end_date": "2026-11-01T00:00:00Z",
"items": [
{
"price": "01HFINTROPRICE000000000000",
"unit_amount": 999,
"currency": "USD",
"recurring": {
"interval": "monthly",
"interval_count": 1
}
}
]
},
{
"start_date": "2026-11-01T00:00:00Z",
"items": [
{
"price": "01HFSTANDARDPRICE000000000",
"unit_amount": 2999,
"currency": "USD",
"recurring": {
"interval": "monthly",
"interval_count": 1
}
}
]
}
],
"metadata": {
"internal_account_id": "acct_123",
"plan": "pro_intro"
}
}'
Who creates it: your backend.
What is created immediately: a schedule.
What to store immediately: schedule_id, Customer ID, internal account ID, and the intended plan.
When a subscription exists: after the first phase activates and the schedule's subscription field is populated.
What confirms access: invoice.paid for the relevant billing period.
What can go wrong: missing default payment method, invalid phase dates, non-recurring phase items, webhook handling gaps, or a failed payment after the subscription exists.
What to store
Store:
- your internal user, account, workspace, or tenant ID;
customer_id;schedule_id;- intended plan or contract mapping;
subscription_idonce the schedule exposes it;- latest schedule
status; - latest subscription
status; - relevant
invoice_idvalues; - webhook event or delivery IDs for idempotency.
What to listen for
Use invoice events for access decisions after the subscription exists.
| Event | Use |
|---|---|
invoice.paid |
Grant or extend access for a paid billing period. |
invoice.payment_failed |
Start recovery and fetch the latest schedule, subscription, and invoice state. |
Do not build public integrations around schedule lifecycle webhook names. Schedule-created, schedule-updated, and schedule-canceled events are not public webhook event types in the current public API reference.
Access decisions
Schedule creation is not access proof.
Use this decision sequence:
- Store the schedule.
- Wait for the schedule to expose a linked
subscription, or retrieve it when needed. - Store the linked
subscription_id. - Use invoice events and latest subscription state to grant, extend, recover, or end access.
- Apply your product policy for trials, grace periods, and cancellations.
For trials, trial_end can start the created subscription in trialing status. Whether trialing customers receive access is your product policy.
Cancellation, release, and fixed duration
Schedules have lifecycle statuses such as NOT_STARTED, ACTIVE, COMPLETED, CANCELED, and RELEASED.
Verified behavior:
end_behavior: RELEASElets the subscription continue billing independently after the schedule finishes.end_behavior: CANCELcancels the linked subscription when the final phase is applied.- releasing an active schedule marks the schedule as
RELEASEDand stops future phase control. - manual schedule cancellation sets the schedule to
CANCELED.
The public API reference describes an optional cancel_subscription request field for manual schedule cancellation. The verified implementation currently cancels a linked subscription when a schedule is canceled. Until the public contract and implementation are reconciled, do not depend on schedule cancellation as a schedule-only operation. Retrieve both the schedule and linked subscription after cancellation.
Common mistakes
- Using schedules for a simple recurring plan.
- Not storing
schedule_idbefore a subscription exists. - Expecting
subscriptionto be populated immediately for a future-start schedule. - Granting paid access from schedule creation.
- Creating a schedule without a default payment method.
- Creating a phase with only one-time items.
- Assuming phase changes produce public
subscription.*webhooks. - Using
send_invoicein schedule settings. - Canceling a schedule and assuming the linked subscription always continues.
Troubleshooting
| Symptom | Check |
|---|---|
| Schedule creation fails | Confirm customer, phases, phase start_date, item currency, item unit_amount, and at least one recurring item per phase. |
| Schedule exists but no subscription exists | Check whether the first phase start_date has arrived. Store schedule_id until subscription is populated. |
| Phase transition did not happen | Retrieve the schedule and inspect status, current_phase_index, current_phase, and next_action_at. |
| Activation fails | Confirm default_settings.default_payment_method is present and belongs to the Customer. |
| Intro price did not change | Retrieve the schedule and linked subscription; confirm the next phase start date and that the later phase has the expected recurring Price. |
| Access was not extended | Confirm invoice.paid was received and mapped to the linked subscription_id. |
| Schedule cancellation was unexpected | Retrieve both the schedule and linked subscription. Do not assume manual schedule cancellation leaves the subscription running until the public contract is reconciled. |

