@@ -94,6 +94,14 @@ export interface FreebuffSubscriptionTierOffer {
9494 purchasable ?: boolean
9595 /** Annual checkout remains unavailable until its Stripe price is configured. */
9696 yearlyPurchasable ?: boolean
97+ /**
98+ * Whether a year of this tier can be bought with ONE payment and no
99+ * auto-renew (checkout body `paymentMode: 'once'`). That checkout is a
100+ * one-time payment, which is what lets it offer the methods a subscription
101+ * cannot: crypto, Alipay / WeChat Pay, iDEAL, Bancontact, and UPI above the
102+ * AutoPay cap. Optional on old servers; absent means no.
103+ */
104+ yearlyPrepaidPurchasable ?: boolean
97105}
98106
99107/**
@@ -351,8 +359,19 @@ export interface FreebuffPriceChange {
351359export interface FreebuffSubscriptionInfo {
352360 /** The caller's tier id, or null when they have no live subscription. */
353361 tierId : string | null
354- /** Entitlement origin. Optional for compatibility with older servers. */
355- source ?: 'stripe' | 'grant'
362+ /**
363+ * Entitlement origin. Optional for compatibility with older servers.
364+ * `prepaid` is a year bought with one payment: it never renews, so it also
365+ * reports `cancelAtPeriodEnd: true` and `renewsAt` is its paid-through date —
366+ * which is how clients that predate this value already describe it
367+ * correctly as ending rather than renewing.
368+ */
369+ source ?: 'stripe' | 'grant' | 'prepaid'
370+ /**
371+ * `prepaid` only: from when another pay-once year can be bought. Buying one
372+ * then extends the plan by a year from its current end, so there is no gap.
373+ */
374+ prepaidRenewableAt ?: string
356375 /** Billing cadence for the live plan. Absent on legacy server payloads. */
357376 billingInterval ?: 'monthly' | 'yearly'
358377 /** Stripe paid-through/renewal instant, distinct from monthly usage reset. */
0 commit comments