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

# Server SDK

> Documentation for @paymint/server

# @paymint/server

Server-side SDK for Paymint billing.

## Installation

```bash theme={null}
npm install @paymint/server
```

> **Note:** For Next.js apps, use `@paymint/nextjs` instead - it includes this package plus React hooks.

## Quick Start

```typescript theme={null}
import { PaymintServer } from '@paymint/server';

const paymint = new PaymintServer({
  apiKey: process.env.PAYMINT_API_KEY!,
  // baseUrl is auto-configured:
  // - Default: https://api.paymint.dev
  // - Local: Set PAYMINT_USE_LOCAL_API=true for localhost:3002
});

// Or override explicitly:
const paymint = new PaymintServer({
  apiKey: process.env.PAYMINT_API_KEY!,
  baseUrl: 'http://localhost:3002', // Only for internal testing
});

// Get all products
const products = await paymint.getProducts();

// Initialize checkout (returns Paddle client token)
const init = await paymint.initialize('customer@example.com');
// init.clientSideToken - for Paddle.js
// init.paddleEnvironment - 'sandbox' or 'production'

// Get billing state (products + subscriptions)
const billing = await paymint.getBilling('customer@example.com');
// billing.products
// billing.subscriptions
// billing.hasActiveSubscription

// Get subscriptions only
const subscriptions = await paymint.getSubscriptions('customer@example.com');

// Cancel subscription
await paymint.cancelSubscription('customer@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period', // or 'immediately'
});

// Pause subscription
await paymint.pauseSubscription('customer@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period',
  resumeAt: '2024-03-01', // optional auto-resume date
});

// Resume subscription
await paymint.resumeSubscription('customer@example.com', 'sub_xxx');

// Activate trial
await paymint.activateSubscription('customer@example.com', 'sub_xxx');
```

## Scoped Customer Pattern

When making multiple calls for the same customer, use `forCustomer()` for cleaner code:

```typescript theme={null}
const paymint = new PaymintServer({ apiKey: process.env.PAYMINT_API_KEY! });

// Without scoped customer
const billing = await paymint.getBilling('user@example.com');
await paymint.cancelSubscription('user@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period'
});

// With scoped customer - cleaner!
const customer = paymint.forCustomer('user@example.com');
const billing = await customer.getBilling();
await customer.cancelSubscription('sub_xxx', { effectiveFrom: 'next_billing_period' });
```

### Scoped Customer Methods

```typescript theme={null}
const customer = paymint.forCustomer('user@example.com');

// All methods - email is already bound
const billing = await customer.getBilling();
const subscriptions = await customer.getSubscriptions();
const init = await customer.initialize();

// Subscription actions
await customer.cancelSubscription('sub_xxx', { effectiveFrom: 'next_billing_period' });
await customer.pauseSubscription('sub_xxx', { effectiveFrom: 'next_billing_period' });
await customer.resumeSubscription('sub_xxx');
await customer.activateSubscription('sub_xxx');
```

## BillingState Type

```typescript theme={null}
interface BillingState {
  products: Product[];
  subscriptions: Subscription[];
  hasActiveSubscription: boolean;
  activeSubscription: Subscription | null;
  isTrialing: boolean;
  isPaused: boolean;
  isCanceled: boolean;
}
```

## Complete Examples

### Check Subscription Access

```typescript theme={null}
import { PaymintServer } from '@paymint/server';

async function checkAccess(email: string) {
  const paymint = new PaymintServer({
    apiKey: process.env.PAYMINT_API_KEY!,
  });

  const billing = await paymint.getBilling(email);

  if (billing.hasActiveSubscription) {
    console.log('User has active subscription:', billing.activeSubscription?.id);
    return { access: true, subscription: billing.activeSubscription };
  }

  if (billing.isTrialing) {
    console.log('User is on trial');
    return { access: true, trial: true };
  }

  return { access: false };
}
```

### Subscription Management

```typescript theme={null}
import { PaymintServer } from '@paymint/server';

async function manageSubscription(email: string, subscriptionId: string) {
  const paymint = new PaymintServer({
    apiKey: process.env.PAYMINT_API_KEY!,
  });

  const customer = paymint.forCustomer(email);

  // Get current state
  const billing = await customer.getBilling();
  const subscription = billing.subscriptions.find(s => s.id === subscriptionId);

  if (!subscription) {
    throw new Error('Subscription not found');
  }

  // Cancel at end of period (recommended)
  if (subscription.status === 'active') {
    await customer.cancelSubscription(subscriptionId, {
      effectiveFrom: 'next_billing_period'
    });
    console.log('Subscription will cancel at end of billing period');
  }

  // Or pause temporarily
  if (subscription.status === 'active') {
    await customer.pauseSubscription(subscriptionId, {
      effectiveFrom: 'next_billing_period',
      resumeAt: '2024-03-01T00:00:00Z' // Auto-resume
    });
    console.log('Subscription paused until March 1st');
  }

  // Resume paused subscription
  if (subscription.status === 'paused') {
    await customer.resumeSubscription(subscriptionId);
    console.log('Subscription resumed');
  }
}
```

### Initialize Checkout

```typescript theme={null}
import { PaymintServer } from '@paymint/server';

async function createCheckout(email: string) {
  const paymint = new PaymintServer({
    apiKey: process.env.PAYMINT_API_KEY!,
  });

  const init = await paymint.initialize(email);

  return {
    token: init.clientSideToken,
    environment: init.paddleEnvironment,
    customerExists: init.customerExists,
  };
}
```

## Error Handling

All errors extend `PaymintError` from `@paymint/shared`:

```typescript theme={null}
import { PaymintServer } from '@paymint/server';
import { PaymintError, ValidationError } from '@paymint/shared';

const paymint = new PaymintServer({ apiKey: process.env.PAYMINT_API_KEY! });

try {
  const billing = await paymint.getBilling('user@example.com');
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Invalid email or parameters:', error.message);
  } else if (error instanceof PaymintError) {
    console.error('Paymint error:', error.message, 'Request ID:', error.requestId);
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## Environment

The API key format determines the environment:

* `paymint_test_xxx` → Sandbox
* `paymint_live_xxx` → Production

## Comparison with @paymint/node

| Use Case                   | Package           | Reason                        |
| -------------------------- | ----------------- | ----------------------------- |
| Full-stack Next.js         | `@paymint/nextjs` | Includes server + React hooks |
| React SPA + custom backend | `@paymint/server` | Server utilities              |
| Raw HTTP access            | `@paymint/node`   | Low-level client              |
| Type definitions only      | `@paymint/shared` | Types and errors              |

## License

MIT
