Subscriptions Required
Give access from the subscription status
Decide access in one function from the stored subscription status, period end and first failed payment time, with a fixed grace period for failed renewals.
How to do it
Map each status to access in one place. Active and trialing give access. Past due gives access for a grace period, such as 7 days, while retries run. Count the grace from the time of the first failed renewal, stored from the failure event. Many providers move the period end forward when they bill the renewal, so a grace counted from it gives a free month. A cancelled subscription keeps access until the paid period ends. Unpaid or ended gives none. Every page, API and background job asks that one function.
Example
const GRACE_DAYS = 7
const DAY_MS = 24 * 60 * 60 * 1000
function hasAccess(subscription, now = new Date()) {
const periodEnd = subscription.currentPeriodEnd.getTime()
switch (subscription.status) {
case 'active':
case 'trialing':
return true
case 'past_due':
return now.getTime() < subscription.firstFailedAt.getTime() + GRACE_DAYS * DAY_MS
case 'canceled':
return now.getTime() < periodEnd
default:
return false
}
}
from datetime import datetime, timedelta, timezone
GRACE = timedelta(days=7)
def has_access(subscription, now: datetime | None = None) -> bool:
now = now or datetime.now(timezone.utc)
match subscription.status:
case "active" | "trialing":
return True
case "past_due":
return now < subscription.first_failed_at + GRACE
case "canceled":
return now < subscription.current_period_end
case _:
return False
How to check
A table test covers every status on the day before and the day after the period end and the grace end. A past due subscription whose period end lies a month ahead loses access 7 days after its failed payment. Search the code for direct reads of the status field outside that function. None are found.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers payments playbook: https://agentwranglers.se/playbook/payments/subscriptions/entitlements-from-status.