Skip to main content

Overview

Activates a PayPal subscription after the user completes approval on PayPal. This endpoint validates the subscription, retrieves plan details from PayPal, and updates the user’s account with subscription status and billing information.

Endpoint

POST /api/payments/activate-subscription

Authentication

Requires authenticated session via NextAuth.js. The endpoint automatically retrieves the user ID from the server-side session.

Request Body

subscriptionId
string
required
PayPal subscription ID returned after user approval
plan
string
Optional plan enum. If provided, must be one of: FREE, STARTER, PROFESSIONAL, AGENCY. The actual plan will be detected from the PayPal subscription details.

Response

success
boolean
Indicates if the subscription was activated successfully
message
string
Human-readable status message
refreshSession
boolean
Signals the frontend to refresh the user session to get updated subscription data

Subscription Activation Flow

When a subscription is activated, the following operations occur:
  1. PayPal Verification: Fetches subscription details from PayPal API
  2. Plan Detection: Maps PayPal plan ID to internal plan using PAYPAL_PLAN_TO_DB_PLAN mapping
  3. Trial Detection: Determines if subscription includes trial period based on next_billing_time
  4. User Update: Updates user record with:
    • Plan level (STARTER, PROFESSIONAL, or AGENCY)
    • PayPal subscription ID
    • Subscription status set to active
    • Billing cycle dates
    • Trial tracking fields
    • White-label enabled (all paid plans include white-label)
  5. Payment Record: Creates initial payment record if payment has been made
  6. Email Notification: Sends upgrade success email to user

PayPal Plan Mapping

The endpoint uses hardcoded PayPal plan ID mappings:
const PAYPAL_PLAN_TO_DB_PLAN = {
  'P-0X464499YG9822634NEQJ5XQ': 'STARTER',      // Starter Trial
  'P-6PJ50716H4431863PNEQKBLQ': 'STARTER',      // Starter Direct
  'P-09P26662R8680522DNEQJ7XY': 'PROFESSIONAL', // Professional Trial
  'P-90W906144W5364313NEQKB5I': 'PROFESSIONAL', // Professional Direct
  'P-7SU477161L382370MNEQKCQQ': 'AGENCY',       // Agency Trial
  'P-0KW62605U4011430FNEQKDCY': 'AGENCY',       // Agency Direct
};

Example Request

curl -X POST https://api.reportr.com/api/payments/activate-subscription \
  -H "Content-Type: application/json" \
  -H "Cookie: next-auth.session-token=..." \
  -d '{
    "subscriptionId": "I-BW452GLLEP1G",
    "plan": "PROFESSIONAL"
  }'

Example Response

Success (200 OK)

{
  "success": true,
  "message": "Subscription activated",
  "refreshSession": true
}

Error: Unauthorized (401)

{
  "error": "Unauthorized"
}

Error: Missing Subscription ID (400)

{
  "error": "Subscription ID is required"
}

Error: Invalid Plan (400)

{
  "error": "Invalid plan"
}

Error: Server Error (500)

{
  "error": "Failed to activate subscription"
}

Database Updates

After successful activation, the User model is updated with:
{
  plan: "PROFESSIONAL",                     // Detected from PayPal
  paypalSubscriptionId: "I-BW452GLLEP1G",
  subscriptionStatus: "active",
  planExpires: null,
  billingCycleStart: "2026-03-04T10:00:00Z",
  billingCycleEnd: "2026-04-04T10:00:00Z",
  trialStartDate: "2026-03-04T10:00:00Z",   // If trial
  trialEndDate: "2026-03-11T10:00:00Z",     // If trial
  trialType: "PAYPAL",
  trialUsed: true,
  whiteLabelEnabled: true,
  signupFlow: "PAID_TRIAL"
}
A Payment record is also created:
{
  userId: "user_id",
  paypalOrderId: "I-BW452GLLEP1G",
  paypalSubscriptionId: "I-BW452GLLEP1G",
  amount: 49.00,
  currency: "USD",
  status: "COMPLETED",
  plan: "PROFESSIONAL",
  metadata: { /* Full PayPal subscription details */ }
}

Error Handling

All errors are logged server-side and return a generic error message to prevent exposing internal details. Check server logs for detailed error information.

Source Code

Implementation: src/app/api/payments/activate-subscription/route.ts:12

Build docs developers (and LLMs) love