import { NextResponse } from 'next/server'
import Stripe from 'stripe'
import { createClient } from '@supabase/supabase-js'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2025-05-28.basil',
})
// Create server-side Supabase client with user session (same pattern as other working APIs)
function createServerSupabaseClient(request: Request) {
const authHeader = request.headers.get('authorization')
return createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
autoRefreshToken: false,
persistSession: false
},
global: {
headers: authHeader ? {
Authorization: authHeader
} : {}
}
}
)
}
export async function POST(req: Request) {
try {
// Get the authorization header
const authHeader = req.headers.get('authorization')
if (!authHeader) {
return NextResponse.json(
{ error: 'Authorization header required' },
{ status: 401 }
)
}
// Create Supabase client with proper auth context (same as other working APIs)
const supabase = createServerSupabaseClient(req)
// Verify the session with Supabase
const { data: { user }, error: authError } = await supabase.auth.getUser()
if (authError || !user) {
return NextResponse.json(
{ error: 'Invalid session' },
{ status: 401 }
)
}
// Get user's subscription to find their Stripe customer ID
const { data: subscription, error: subscriptionError } = await supabase
.from('subscriptions')
.select('id, status, price_id, current_period_start, current_period_end, cancel_at_period_end, stripe_customer_id')
.eq('user_id', user.id)
.in('status', ['active', 'trialing', 'past_due']) // Include all manageable statuses
.order('created_at', { ascending: false })
.maybeSingle() // Use maybeSingle() instead of single() to handle 0 or 1 rows gracefully
if (subscriptionError) {
console.error('Error fetching subscription:', subscriptionError)
return NextResponse.json(
{ error: 'Error fetching subscription data.' },
{ status: 500 }
)
}
if (!subscription?.stripe_customer_id) {
return NextResponse.json(
{ error: 'No subscription found. You need an active subscription to manage billing.' },
{ status: 404 }
)
}
// Determine the return URL
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000'
const returnUrl = `${baseUrl}/dashboard/billing`
// Create the portal session
const portalSession = await stripe.billingPortal.sessions.create({
customer: subscription.stripe_customer_id,
return_url: returnUrl,
})
return NextResponse.json({ url: portalSession.url })
} catch (error) {
console.error('Error creating portal session:', error)
return NextResponse.json(
{ error: `Error creating portal session: ${error instanceof Error ? error.message : 'Unknown error'}` },
{ status: 500 }
)
}
}