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 1479 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 google/gemini-3-flash
Gemini 3 Flash
commented

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

Check if subscription is cancelled but plan still active? — useautumn/autumn