diff --git a/apps/minting-service/src/lib/handlers.ts b/apps/minting-service/src/lib/handlers.ts index 574024b6..e2545679 100644 --- a/apps/minting-service/src/lib/handlers.ts +++ b/apps/minting-service/src/lib/handlers.ts @@ -101,8 +101,17 @@ function readCustomerId(subscription: Stripe.Subscription): string { } function periodEnd(subscription: Stripe.Subscription): Date { - // current_period_end is unix seconds; convert to Date. - const epoch = (subscription as unknown as { current_period_end?: number }).current_period_end; + // current_period_end is unix seconds. As of Stripe API 2026-04-22, it moved + // off the subscription object and onto each subscription item. Read item + // first, fall back to the legacy subscription-level field for older API + // versions or replayed historical events. + const subRecord = subscription as unknown as { + current_period_end?: number; + items?: { data?: Array<{ current_period_end?: number }> }; + }; + const itemEpoch = subRecord.items?.data?.[0]?.current_period_end; + const subEpoch = subRecord.current_period_end; + const epoch = itemEpoch ?? subEpoch; if (!epoch) { throw new Error(`subscription ${subscription.id} has no current_period_end`); } diff --git a/pricing/tiers.generated.ts b/pricing/tiers.generated.ts index aedd6752..8c2853cf 100644 --- a/pricing/tiers.generated.ts +++ b/pricing/tiers.generated.ts @@ -4,7 +4,7 @@ import type { TierSlug, BillingCycle } from './tiers.config'; type BuyableSlug = Exclude; -// Empty stub — run `STRIPE_SECRET_KEY=sk_... pnpm tsx scripts/stripe/sync-products.ts` -// to populate. Until that runs, the checkout API returns a 503 with a helpful -// message. -export const STRIPE_PRICE_IDS: Partial>> = {}; +export const STRIPE_PRICE_IDS: Partial>> = { + developer_seat: { monthly: "price_1TapR1GYRsLErhxb83221xMU", annual: "price_1TapR1GYRsLErhxb67dc67h1" }, + team: { monthly: "price_1TapR2GYRsLErhxbBbrJMLpk", annual: "price_1TapR2GYRsLErhxbYsWAkYuE" }, +};