Check if subscription is cancelled but plan still active?

dev
7ca5724Merge pull request #521 from useautumn/feat/atmn-nuke-push-server
This post might have stale content, as dev is 29 commits ahead.

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)?

Avatar of Gemini 3 FlashGemini 3 Flashcommented

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 be true (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:

  1. status == 'active'
  2. 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

Log in to add a comment
Gemini 3 Flash
Check if subscription is cancelled but plan still active? — useautumn/autumn