Check if subscription is cancelled but plan still active?
How can I check if a user has a plan that is currently active but the subscription was cancelled (next billing cycle the plan will be deactivated)?
To check if a user has a plan that is currently active but scheduled for deactivation (cancelled but still in its grace period), you can use two main methods depending on your use case:
###1. Using the /check Endpoint
When you call the /check endpoint for a specific product, Autumn evaluates if the user still has access and returns their current cancellation status.
- Endpoint:
POST /v1/check - Logic:
allowed: Will betrue(since the plan is still active).status: Will be'canceled'.
In the source code (server/src/internal/api/check/handlers/handleProductCheck.ts), the logic is defined as follows:
allowed:
cusProduct.status === CusProductStatus.Active ||
cusProduct.status === CusProductStatus.PastDue,
status: notNullish(cusProduct.canceled_at)
? "canceled"
: onTrial
? "trialing"
: cusProduct.status,
###2. Inspecting the Customer Object
If you fetch the full customer data (e.g., via GET /v1/customers/:id), you can inspect the subscriptions array.
- Logic:
status: Will be'active'.canceled_at: Will contain a timestamp (non-null).expires_at: This timestamp indicates exactly when the plan will be deactivated.
The ApiSubscription model (shared/api/customers/cusPlans/apiSubscription.ts) defines these fields:
export const ApiSubscriptionSchema = z.object({
// ...
status: z.enum(["active", "scheduled", "expired"]),
canceled_at: z.number().nullable(),
expires_at: z.number().nullable(),
current_period_end: z.number().nullable(),
// ...
});
###Summary
If a user cancels their subscription in the middle of a billing cycle, Autumn keeps the status as "active" (or returns allowed: true in checks) but sets the canceled_at timestamp. You can identify this state by checking:
status == 'active'canceled_at != null
The expires_at or current_period_end field will tell you the date of the next billing cycle when the plan will finally move to an "expired" state.
END OF POST