> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nullpass.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Polar Portal

> Redirect to Polar customer portal

## Endpoint

```
GET /api/polar/portal
```

## Overview

Redirects the authenticated user to their Polar customer portal where they can manage their subscription, update payment methods, and view invoices.

## Request

Requires authentication via Bearer token. User must have a DROP service entitlement with a Polar customer ID.

## Response

307 redirect to Polar customer portal URL.

## Implementation Details

### Code Reference

```7:50:nullpass_clean/src/app/api/polar/portal/route.ts theme={null}
export const GET = async (req: NextRequest) => {
  const corsResponse = handleCors(req)
  if (corsResponse) return corsResponse

  const blocked = await protectRoute(req, { requested: 2 })
  if (blocked) return blocked

  const auth = await requireAuth(req)
  if ('error' in auth) return auth.error
  
  const entitlement = await prisma.userServiceEntitlement.findUnique({
    where: {
      userId_service: {
        userId: auth.userId,
        service: 'DROP',
      },
    },
    select: { polarCustomerId: true },
  })

  if (!entitlement?.polarCustomerId) {
    return errorResponse('No Polar customer ID found. Please contact support.', 400, req.headers.get('origin'))
  }

  try {
    const response = await fetch(`https://api.polar.sh/v1/customers/${entitlement.polarCustomerId}`, {
      headers: {
        'Authorization': `Bearer ${process.env.POLAR_ACCESS_TOKEN}`,
        'Content-Type': 'application/json'
      }
    })
    
    if (!response.ok) {
      return errorResponse('Customer not found in Polar. Please contact support to resolve this issue.', 400, req.headers.get('origin'))
    }
  } catch (error) {
    return errorResponse('Failed to verify customer. Please contact support.', 500, req.headers.get('origin'))
  }

  const polarServer = process.env.POLAR_SERVER === 'sandbox' ? 'sandbox-' : ''
  const portalUrl = `https://${polarServer}polar.sh/portal/${entitlement.polarCustomerId}`

  return NextResponse.redirect(portalUrl, 307)
}
```

## Status Codes

<ResponseField name="307" type="Temporary Redirect">
  Redirect to Polar portal
</ResponseField>

<ResponseField name="400" type="Bad Request">
  No Polar customer ID found or customer not found in Polar
</ResponseField>

<ResponseField name="401" type="Unauthorized">
  Missing or invalid authentication token
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  Failed to verify customer with Polar
</ResponseField>

## Example Request

```bash theme={null}
curl -X GET https://auth.nullpass.xyz/api/polar/portal \
  -H "Authorization: Bearer YOUR_TOKEN"
```

## Portal Features

The Polar customer portal allows users to:

* View subscription details
* Update payment methods
* View invoices and billing history
* Cancel subscriptions
* Update billing information

## Environment Variables

<ResponseField name="POLAR_ACCESS_TOKEN" type="string" required>
  Polar API access token
</ResponseField>

<ResponseField name="POLAR_SERVER" type="string" default="production">
  Polar server: `"sandbox"` or `"production"`. Affects portal URL.
</ResponseField>

## Notes

* Only works for DROP service
* Requires existing Polar customer ID
* Customer is verified with Polar before redirect
* Portal URL depends on POLAR\_SERVER environment variable
