> ## 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.

# Node.js SDK

> Documentation for @paymint/node

# @paymint/node

Low-level HTTP client for the Paymint API.

## Installation

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

> **Note:** For most use cases, use `@paymint/server` or `@paymint/nextjs` instead. This package provides the underlying HTTP client.

## Quick Start

```typescript theme={null}
import { PaymintClient } from '@paymint/node';

const client = new PaymintClient({
  apiKey: 'paymint_test_xxx', // or paymint_live_xxx for production
});

// Get products
const products = await client.products.list();

// Initialize checkout
const init = await client.checkout.initialize({ email: 'customer@example.com' });

// Get subscriptions
const subscriptions = await client.subscriptions.list({ email: 'customer@example.com' });

// Cancel subscription
await client.subscriptions.cancel('customer@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period',
});
```

## Configuration

### API Key Format

* `paymint_test_xxx` - Sandbox/test environment
* `paymint_live_xxx` - Production environment

The environment is automatically detected from your API key.

### Client Options

```typescript theme={null}
const client = new PaymintClient({
  apiKey: 'paymint_test_xxx',     // Required
  baseUrl: 'https://api.paymint.dev', // Optional, defaults to api.paymint.dev
  timeout: 30000,                      // Optional, request timeout in ms
});
```

## Resources

The client is organized into resources that map to API endpoints:

### `client.products`

```typescript theme={null}
// List all products with prices
const products = await client.products.list();

// Product structure
interface Product {
  id: string;
  name: string;
  description: string | null;
  prices: Price[];
}

interface Price {
  id: string;
  name: string;
  description: string | null;
  unitPrice: {
    amount: string;
    currencyCode: string;
  };
  billingCycle: {
    interval: 'month' | 'year';
    frequency: number;
  };
  trialPeriod: {
    interval: 'day';
    frequency: number;
  } | null;
}
```

### `client.checkout`

```typescript theme={null}
// Initialize checkout for a customer
const init = await client.checkout.initialize({
  email: 'user@example.com',
});

// Returns
interface InitializeResponse {
  clientSideToken: string;      // Pass to Paddle.js
  paddleEnvironment: 'sandbox' | 'production';
  customerExists: boolean;
}

// Use with Paddle.js
Paddle.Initialize({
  token: init.clientSideToken,
  environment: init.paddleEnvironment,
});
```

### `client.subscriptions`

```typescript theme={null}
// List subscriptions for a customer
const subscriptions = await client.subscriptions.list({
  email: 'user@example.com',
});

// Cancel a subscription
await client.subscriptions.cancel('user@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period', // or 'immediately'
});

// Pause a subscription
await client.subscriptions.pause('user@example.com', 'sub_xxx', {
  effectiveFrom: 'next_billing_period',
  resumeAt: '2024-03-01T00:00:00Z', // Optional: auto-resume
});

// Resume a paused subscription
await client.subscriptions.resume('user@example.com', 'sub_xxx', {
  effectiveFrom: 'immediately',
});

// Activate a trialing subscription
await client.subscriptions.activate('user@example.com', 'sub_xxx');
```

## Error Handling

All errors extend `PaymintError`:

```typescript theme={null}
import {
  PaymintClient,
  PaymintError,
  AuthenticationError,
  ValidationError,
  NotFoundError,
  RateLimitError,
  NetworkError,
} from '@paymint/node';

try {
  const products = await client.products.list();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof ValidationError) {
    console.error('Invalid request:', error.message);
  } else if (error instanceof NotFoundError) {
    console.error('Resource not found');
  } else if (error instanceof RateLimitError) {
    console.error('Rate limited. Retry after:', error.retryAfter);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof PaymintError) {
    console.error('Paymint error:', error.message, error.requestId);
  } else {
    console.error('Unknown error:', error);
  }
}
```

### Error Types

| Error                 | Status | Description                  |
| --------------------- | ------ | ---------------------------- |
| `AuthenticationError` | 401    | Invalid API key              |
| `ValidationError`     | 400    | Invalid request parameters   |
| `NotFoundError`       | 404    | Resource not found           |
| `RateLimitError`      | 429    | Too many requests            |
| `NetworkError`        | -      | Connection or timeout issues |

## TypeScript Support

Full TypeScript types are included:

```typescript theme={null}
import type {
  Product,
  Price,
  Subscription,
  SubscriptionStatus,
  InitializeRequest,
  InitializeResponse,
  CancelSubscriptionOptions,
  PauseSubscriptionOptions,
  ResumeSubscriptionOptions,
} from '@paymint/node';
```

## Complete Example

```typescript theme={null}
import { PaymintClient, PaymintError } from '@paymint/node';

async function billingExample() {
  const client = new PaymintClient({
    apiKey: process.env.PAYMINT_API_KEY!,
  });

  try {
    // Get available products
    const products = await client.products.list();
    console.log('Available products:', products.map(p => p.name));

    // Initialize checkout
    const init = await client.checkout.initialize({
      email: 'customer@example.com',
    });
    console.log('Checkout token:', init.clientSideToken);

    // Check existing subscriptions
    const subscriptions = await client.subscriptions.list({
      email: 'customer@example.com',
    });

    const activeSubscription = subscriptions.find(
      s => s.status === 'active' || s.status === 'trialing'
    );

    if (activeSubscription) {
      console.log('Active subscription:', activeSubscription.id);
      
      // Cancel at end of period
      await client.subscriptions.cancel(
        'customer@example.com',
        activeSubscription.id,
        { effectiveFrom: 'next_billing_period' }
      );
      console.log('Subscription will cancel at end of period');
    }

  } catch (error) {
    if (error instanceof PaymintError) {
      console.error('Billing error:', error.message);
    } else {
      throw error;
    }
  }
}
```

## Advanced Usage

### Custom Base URL

For testing or self-hosted instances:

```typescript theme={null}
const client = new PaymintClient({
  apiKey: 'paymint_test_xxx',
  baseUrl: 'http://localhost:3002', // Override for local development
});
```

**Environment-based Auto-Configuration:**

By default, all SDKs connect to `https://api.paymint.dev`. To use a local API server during Paymint internal development:

```bash theme={null}
PAYMINT_USE_LOCAL_API=true npm run dev
```

This will automatically use `http://localhost:3002` instead of the production API.

### Timeout Configuration

```typescript theme={null}
const client = new PaymintClient({
  apiKey: 'paymint_test_xxx',
  timeout: 10000, // 10 seconds
});
```

### Request ID Tracking

All errors include a request ID for support:

```typescript theme={null}
try {
  await client.products.list();
} catch (error) {
  if (error instanceof PaymintError) {
    console.log('Request ID:', error.requestId);
    // Include this when contacting support
  }
}
```

## License

MIT
