Lifecycle and statuses

Use this page to understand subscription statuses and the fields your backend should inspect before granting, extending, recovering, or ending access.

Subscription status is one signal. For paid access, combine status with invoice events and billing-period fields.

What this page is for

This page explains:

  • subscription lifecycle states;
  • which statuses are active, recoverable, terminal, or uncommon;
  • how billing-period fields affect access decisions;
  • how cancellation fields affect access decisions;
  • how payment failure and recovery fit into the lifecycle.

Subscription lifecycle overview

Most subscription integrations move through this shape:

  1. The subscription is created.
  2. Paypercut attempts the first payment or waits for a trial or anchor.
  3. The subscription becomes active, trialing, past_due, or fails before creation depending on the flow.
  4. Paypercut creates invoices for billing periods.
  5. Your backend uses invoice events to grant, extend, or recover access.
  6. The subscription eventually continues, is canceled, or reaches another terminal state.

Status reference

Status What it means Should the customer have access? What your backend should do
incomplete Subscription exists, but the first payment has not been fully collected yet. Usually no paid access unless your product deliberately allows a grace state. Wait for invoice/payment outcome or retrieve latest state before granting access.
trialing Subscription is in a trial period and no charge is due until the trial ends. Merchant policy. Grant trial access only if your product supports it. Track trial_start and trial_end; prepare for first billing at trial end.
active Subscription is active and billing normally. Usually yes, if the relevant billing period is paid or otherwise allowed by your policy. Keep access aligned with invoice.paid, current_period_end, and your plan mapping.
past_due A recent automatic charge failed and recovery is needed. Merchant policy. Some products allow a grace period; others restrict access. Handle invoice.payment_failed, notify the customer, and recover with a valid payment method.
incomplete_expired Initial payment retries for a default_incomplete subscription were exhausted. Terminal. No paid access. Stop provisioning and ask the customer to start a new subscription flow.
canceled Subscription has been canceled. Terminal. No access after the effective end of service. Stop future billing and end access according to your cancellation policy.
unpaid Public enum value for unpaid subscriptions after failed collection. Not verified as a primary public flow in this phase. Treat defensively as non-active unless your account has explicit guidance. Retrieve latest state and decide recovery or support action.
paused Public enum value for paused billing. Not verified as a primary public flow in this phase. Merchant policy. Retrieve latest state and avoid assuming billing is continuing.

Access decision guidance

Use a layered decision:

  1. Map the subscription to your internal account.
  2. Check the latest subscription status.
  3. Check invoice events for the billing period.
  4. Check current_period_start and current_period_end.
  5. Check cancellation fields.
  6. Apply your product policy for trials, grace periods, and failed payments.

invoice.paid is the main paid-period signal. invoice.payment_failed is the main recovery signal. Payment and PaymentIntent events are useful for support and reconciliation, but they should not be the primary subscription access contract.

Billing period fields

Field Use
current_period_start Start of the current billing period.
current_period_end End of the current billing period. Use this when deciding how long paid access should last.
next_billing_date Next scheduled billing date. Useful for customer-facing billing UI and support.
billing_cycle_anchor Reference point for future billing dates.

Do not extend access only from next_billing_date. Use paid invoice events and the current billing period.

Cancellation fields

Field Use
cancel_at_period_end Indicates a subscription is intended to cancel at the end of the current period.
cancel_at Indicates a scheduled cancellation date when present.
canceled_at Timestamp when cancellation was recorded.
ended_at Timestamp when the subscription ended.
cancellation_details Reason or feedback details attached to cancellation.

For immediate cancellation, end access according to your product policy and latest subscription state.

For period-end or scheduled cancellation, the public OpenAPI describes cancel_at_period_end and cancel_at, but the verified service path needs product/API confirmation before this guide gives detailed task instructions. Until that is resolved, retrieve the subscription after cancellation changes and use the returned fields as the source of truth.

Payment failure and recovery states

When collection fails:

  1. Paypercut sends invoice.payment_failed.
  2. The subscription can move to past_due.
  3. Your backend should notify the customer or show recovery UI.
  4. After the customer has a valid payment method, your backend can use resume for eligible past_due automatic-collection subscriptions.
  5. A successful resume moves the subscription back to active.
  6. A failed resume returns 402 and leaves the subscription past_due.

Trial states

trialing is externally visible. During trial, Paypercut does not collect the initial charge until the trial ends.

Whether a trialing customer has product access is your product policy. If you grant trial access, store the trial dates and define what happens when the trial ends without successful payment.

Reserved or uncommon statuses

The public enum includes paused and unpaid. This phase did not verify a public beginner flow that creates those states. Treat them defensively:

  • do not assume billing is continuing;
  • retrieve latest subscription and invoice state;
  • avoid granting paid access unless your product policy explicitly allows it.

Common mistakes

  • Granting access from the Checkout success URL.
  • Treating 201 Created from direct creation as paid access proof.
  • Ignoring invoice.payment_failed.
  • Ending access immediately on every failed payment without checking product grace-period policy.
  • Assuming trialing always grants access.
  • Assuming paused or unpaid behave like active.