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

# JavaScript SDK

> Complete guide for integrating SnapPay with JavaScript/Node.js applications using modern async patterns

## Overview

The SnapPay JavaScript SDK provides a comprehensive interface for integrating payment processing, subscription management, and real-time event streaming into your JavaScript/Node.js applications. Built with modern async/await patterns and robust error handling, it offers seamless integration with SnapPay's complete platform.

**Requirements:** Node.js 18+

### Key Features

* **Modern async/await design** with fetch API for optimal performance
* **Comprehensive error handling** with typed error responses
* **Real-time event streaming** via Server-Sent Events (SSE)
* **Service-based architecture** for organized functionality
* **Automatic retry logic** and error handling
* **Environment-based configuration**
* **TypeScript support** with full type definitions

## Installation

```bash theme={null}
npm install @snappay/sdk
```

## Configuration & Initialization

The SDK is configured through environment variables and the client's constructor. All operations require proper authentication and should use async/await patterns for optimal resource management.

### API Key Authentication

Authentication is handled via an API key that must start with `pk_test_` (for testing) or `pk_live_` (for production). Configure your API key in one of these ways:

**Environment Variable (Recommended):**

```bash theme={null}
export SNAPPAY_API_KEY="pk_test_xxxxxxxxxx"
```

**Direct Configuration:**

```javascript theme={null}
import { SnapPay } from "@snappay/sdk";

// Using environment variable (recommended)
const client = new SnapPay();

// Using direct API key
const clientWithKey = new SnapPay("pk_test_xxxxxxxxxx");
```

## Core Methods

All methods are async functions that return promises and must be called with `await`. The SDK uses a service-based architecture where methods are organized into logical groups: `customers`, `checkout`, `access`, and `usage`.

### Customer Management

#### customers.get

Retrieves or creates a customer record (upsert logic).

```javascript theme={null}
const result = await client.customers.get(
  "cus_123",
  "user@example.com",
  "John Doe"
);
if (!result.ok) {
  console.error(result.error.message);
} else {
  const customer = result.data;
  console.log(`Customer ID: ${customer.customerId}`);
}
```

**Parameters:**

* `customerId` (string): Customer identifier
* `email` (string, optional): Customer email address
* `name` (string, optional): Customer full name

**Returns:** `Customer` object with:

* `customerId` (string): SnapPay customer ID
* `email` (string): Customer email
* `name` (string): Customer name

### Checkout Sessions

#### checkout.createSession

Creates a payment checkout session URL for customer purchases.

```javascript theme={null}
import { Provider } from "@snappay/sdk";

const result = await client.checkout.createSession(
  "cus_123",
  "premium-plan",
  "https://yourapp.com/success",
  "https://yourapp.com/cancel", // Optional
  "price_id" // Optional priceId
);
if (!result.ok) {
  console.error(result.error.message);
} else {
  console.log(`Checkout URL: ${result.data.url}`);
}
```

**Parameters:**

* `customerId` (string): SnapPay customer ID
* `productId` (string): Product ID from your SnapPay dashboard
* `successUrl` (string): URL to redirect after successful payment
* `cancelUrl` (string, optional): URL to redirect on cancellation
* `priceId` (string, optional): The optional price ID

**Returns:** `CheckoutSession` object with:

* `sessionId` (string): Unique session identifier
* `url` (string): Checkout URL for customer
* `expiresAt` (string): Session expiration timestamp

### Access Control

#### access.check

Checks if a customer has access to a specific feature based on their subscription and usage limits.

```javascript theme={null}
const result = await client.access.check("cus_123", "premium-features");
if (!result.ok) {
  console.error(result.error.message);
} else {
  const access = result.data;
  if (access.hasAccess) {
    const { usage, allowance } = access;
    if (usage != null && allowance != null) {
      console.log(`Access granted. ${usage}/${allowance} used`);
    } else {
      console.log("Access granted (unlimited feature)");
    }
  } else {
    console.log("Access denied. Upgrade required.");
  }
}
```

**Parameters:**

* `customerId` (string): SnapPay customer ID
* `featureId` (string): Feature identifier

**Returns:** `AccessCheck` object with:

* `hasAccess` (boolean): Whether customer has access
* `featureId` (string): Feature being checked
* `usage` (number | null): Current usage (null if unlimited/no access)
* `allowance` (number | null): Usage limit (null if unlimited/no access)
* `nextResetAt` (number | null): Next reset timestamp in epoch seconds (null if unlimited/no access)

### Usage Tracking

#### usage.track

Reports usage for a metered feature. This action is idempotent to prevent duplicate tracking.

```javascript theme={null}
const result = await client.usage.track(
  "cus_123", // customer ID
  "ai-messages", // feature ID
  1 // usage
);
if (!result.ok) {
  console.error(result.error.message);
} else {
  console.log(`Usage tracked successfully: ${result.data.usageTotal}`);
}
```

**Parameters:**

* `customerId` (string): SnapPay customer ID
* `featureId` (string): Feature identifier for usage tracking
* `usage` (number): Usage amount to track
* `idempotencyKey` (string, optional): Prevents duplicate tracking (random UUID if not set)

**Returns:** `TrackUsageResponse` object with tracking confirmation details.

* `customerId` (string): The ID of the customer whose usage is being tracked.
* `featureId` (string): The ID of the feature being tracked for usage.
* `usageRecorded` (number): The amount of usage recorded in this operation.
* `usageTotal` (number): The total usage amount after this operation.
* `timestamp` (string): The timestamp when the usage was recorded.
* `idempotencyKey` (string): A unique key to prevent duplicate tracking of this operation.

#### usage.get

Retrieves current usage details for a customer's feature.

```javascript theme={null}
const result = await client.usage.get("cus_123", "ai-messages");
if (!result.ok) {
  console.error(result.error.message);
} else {
  const items = result.data;
  for (const usage of items) {
    console.log(`Total usage: ${usage.totalUsage}`);
    if (usage.remaining != null) console.log(`Remaining: ${usage.remaining}`);
    if (usage.limit != null) console.log(`Limit: ${usage.limit}`);
  }
}
```

**Parameters:**

* `customerId` (string): SnapPay customer ID
* `featureId` (string): Feature identifier

**Returns:** `GetUsageResponse[]` array with items containing:

* `totalUsage` (number)
* `productId` (string)
* `featureId` (string)
* `remaining` (number | null)
* `limit` (number | null)
* `nextResetAt` (number | null)

## Real-time Event Handling

**Say goodbye to webhook hell!** SnapPay eliminates the complexity of managing payment webhooks by processing all provider webhooks (Stripe, PayPal, etc.) internally and delivering clean, structured events directly to your application via Server-Sent Events (SSE).

### 🚫 What You DON'T Need:

* **No webhook endpoints** to create and maintain
* **No webhook signature verification**
* **No webhook retry logic** or failure handling
* **No webhook security concerns**
* **No debugging webhook delivery issues**

### ✅ What You GET:

* **Real-time events** delivered instantly to your application
* **Guaranteed delivery** with automatic reconnection
* **Clean, structured data** - no raw webhook payloads
* **Multiple consumption patterns** to fit your architecture
* **Type-safe event objects** with full IDE support

### Supported Events

See the list of supported events: [Server-sent Event Types](/events/index)

### Stream Events (Async Iterator)

Simply iterate over events as they arrive - SnapPay handles all the webhook complexity behind the scenes:

```javascript theme={null}
import { SnapPay } from "@snappay/sdk";

async function main() {
  const client = new SnapPay();
  for await (const event of client.streamEvents()) {
    console.log(`Event: ${event.type}`);
    console.log(`ID: ${event.id}`);
    console.log(`Data:`, event.data);
  }
}

main().catch(console.error);
```

### Event Handlers

Set up handlers for specific payment events - SnapPay converts complex webhook payloads into simple, actionable events:

```javascript theme={null}
import { SnapPay, SSEEventType } from "@snappay/sdk";

function handleSubscriptionUpdated(event) {
  console.log("Subscription updated:", event.data);
}

function handleAny(event) {
  console.log("Event:", event.type, event.data);
}

async function main() {
  const client = new SnapPay();
  client.onEvent(SSEEventType.SUBSCRIPTION_UPDATED, handleSubscriptionUpdated);
  client.onAnyEvent(handleAny);
  await client.startEvents();
  await new Promise((resolve) => setTimeout(resolve, 60000));
}

main().catch(console.error);
```

## Error Handling

The SDK provides comprehensive error handling with typed exceptions:

```javascript theme={null}
import {
  SnapPay,
  SnapPayError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  NotFoundError,
} from "@snappay/sdk";

async function comprehensiveErrorHandling() {
  const client = new SnapPay();

  try {
    const customer = await client.customers.get("cus_123", "test@example.com");
  } catch (error) {
    if (error instanceof AuthenticationError) {
      console.log(`Invalid API key: ${error.message}`);
    } else if (error instanceof ValidationError) {
      console.log(`Invalid parameters: ${error.message}`);
    } else if (error instanceof RateLimitError) {
      console.log(`Rate limit exceeded: ${error.message}`);
    } else if (error instanceof NotFoundError) {
      console.log(`Resource not found: ${error.message}`);
    } else if (error instanceof SnapPayError) {
      console.log(`General SnapPay error: ${error.message}`);
    } else {
      console.log(`Unexpected error: ${error.message}`);
    }
  }
}

comprehensiveErrorHandling().catch(console.error);
```

### Exception Hierarchy

```javascript theme={null}
SnapPayError                    // Base exception
├── AuthenticationError          // Invalid API key or authentication
├── ValidationError              // Invalid parameters or request data
├── RateLimitError              // API rate limit exceeded
├── NotFoundError               // Resource not found
└── ServerError                 // Server-side errors (5xx responses)
```
