Skip to main content

Overview

After a customer completes checkout, the SDK provides helpers to manage the full purchase lifecycle:
  • Cancel renewal — stop auto-renewal; access continues until the period ends
  • Reactivate renewal — undo a pending cancellation while still in the active period
  • Activate plan — activate a product for a customer on a specific plan without checkout (free units or credit balance)
  • Plan switching — activating a different plan automatically expires the current purchase and creates a new one
All helpers follow the same pattern: pass the incoming Request object and a body, get back either a data object or a NextResponse error.

Cancel renewal

Cancels auto-renewal on a purchase. The customer keeps access until the current billing period ends.
import { cancelRenewal } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { purchaseRef, reason } = await request.json()
  const result = await cancelRenewal(request, { purchaseRef, reason })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}
ParameterTypeRequiredDescription
purchaseRefstringYesThe purchase reference to cancel
reasonstringNoOptional cancellation reason
The purchase remains active with cancelledAt set. When the billing period ends, the purchase transitions to expired.

Reactivate renewal

Undoes a pending cancellation, restoring auto-renewal. Only works while the purchase is still active (before the period ends).
import { reactivateRenewal } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { purchaseRef } = await request.json()
  const result = await reactivateRenewal(request, { purchaseRef })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}
ParameterTypeRequiredDescription
purchaseRefstringYesThe purchase reference to reactivate
Preconditions:
  • Purchase status must be active
  • cancelledAt must be set (cancellation is pending)
  • endDate must not have passed
On success, cancelledAt is cleared and autoRenew is restored. A purchase.updated webhook fires.

Activate plan

Activates a product for a customer on a specific plan without going through checkout. Useful for free plans, credit-based activation, or programmatic plan assignment.
import { activatePlan } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { productRef, planRef } = await request.json()
  const result = await activatePlan(request, { productRef, planRef })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}
ParameterTypeRequiredDescription
productRefstringYesThe product to activate
planRefstringYesThe plan to activate on

Response statuses

StatusMeaning
activatedPurchase created successfully
already_activeCustomer already has an active purchase on this plan
topup_requiredCustomer needs more credits — response includes creditBalance and creditsPerUnit
payment_requiredPlan requires payment — response includes checkoutUrl and checkoutSessionId
invalidInvalid product or plan reference
const result = await activatePlan(request, { productRef, planRef })

if (!(result instanceof NextResponse)) {
  switch (result.status) {
    case 'activated':
      // Purchase created — result.purchaseRef is available
      break
    case 'topup_required':
      // Show top-up UI with result.creditBalance and result.creditsPerUnit
      break
    case 'payment_required':
      // Redirect to result.checkoutUrl
      break
  }
}

Plan switching

When a customer already has an active purchase on a product and you call activatePlan with a different planRef, the SDK automatically:
  1. Expires the existing purchase (fires purchase.expired webhook)
  2. Creates a new purchase on the requested plan (fires purchase.created webhook)
No special API call is needed — activatePlan handles the switch.
// Customer is on pln_basic, switch to pln_pro
const result = await activatePlan(request, {
  productRef: 'prd_myapi',
  planRef: 'pln_pro',
})
// result.status === 'activated' if the switch succeeded
Plan switching immediately expires the old purchase. If the old plan was a paid recurring plan, consider whether you need to handle proration or credits on your side.

Complete Next.js example

app/api/
├── cancel-renewal/route.ts
├── reactivate-renewal/route.ts
├── activate-plan/route.ts
└── ...
// app/api/cancel-renewal/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { cancelRenewal } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { purchaseRef, reason } = await request.json()
  const result = await cancelRenewal(request, { purchaseRef, reason })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}
// app/api/reactivate-renewal/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { reactivateRenewal } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { purchaseRef } = await request.json()
  const result = await reactivateRenewal(request, { purchaseRef })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}
// app/api/activate-plan/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { activatePlan } from '@solvapay/next'

export async function POST(request: NextRequest) {
  const { productRef, planRef } = await request.json()
  const result = await activatePlan(request, { productRef, planRef })
  return result instanceof NextResponse ? result : NextResponse.json(result)
}

Next steps

  • Webhooks — handle purchase.updated, purchase.expired, and purchase.created events from lifecycle changes
  • Billing — understand billing cycles, renewal processing, and purchase states
  • Next.js guide — full Next.js integration walkthrough