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

# Node.js SDK reference

> Method-by-method reference for the official Pocketsflow Node.js and TypeScript SDK.

This page is the method reference for the official [`pocketsflow`](https://www.npmjs.com/package/pocketsflow) package. For installation and a first request, start with the [SDK quickstart](/api-reference/sdk).

The SDK is server-side only and is backed by the same API key used by the REST API. It is written in TypeScript and ships its type declarations with every release.

## Client

```ts theme={null}
import { Pocketsflow } from "pocketsflow";

const pocketsflow = new Pocketsflow({
  apiKey: process.env.POCKETSFLOW_API_KEY!,
  baseUrl: "https://api.pocketsflow.com",
  timeout: 30_000,
});
```

### `PocketsflowConfig`

| Property  | Type     | Required | Default                       | Description                                           |
| --------- | -------- | -------- | ----------------------------- | ----------------------------------------------------- |
| `apiKey`  | `string` | Yes      | —                             | A `pk_live_...` or `pk_test_...` API key.             |
| `baseUrl` | `string` | No       | `https://api.pocketsflow.com` | API origin. Useful for local or staging environments. |
| `timeout` | `number` | No       | `30000`                       | Request timeout in milliseconds.                      |

## Method index

| Namespace            | Methods                                             |
| -------------------- | --------------------------------------------------- |
| `products`           | `list`, `get`, `create`, `update`, `delete`, `copy` |
| `variants`           | `create`, `delete`                                  |
| `orders`             | `list`, `get`                                       |
| `customers`          | `list`, `get`                                       |
| `reviews`            | `list`                                              |
| `discounts`          | `list`, `get`, `create`, `update`, `delete`         |
| `upsells`            | `list`, `get`, `create`, `update`, `delete`         |
| `subscriptions`      | `list`, `get`, `cancel`, `refund`                   |
| `subscriptionOffers` | `list`, `get`, `create`                             |
| `webhooks`           | `list`, `get`, `create`, `update`, `delete`, `test` |
| `users`              | `me`, `update`                                      |
| `checkout`           | `create`                                            |
| `refunds`            | `list`, `get`, `create`                             |

## Products

One-time products that buyers can purchase through hosted checkout.

| Method   | Signature                                 | Returns                                 |
| -------- | ----------------------------------------- | --------------------------------------- |
| `list`   | `pocketsflow.products.list()`             | `Promise<Product[]>`                    |
| `get`    | `pocketsflow.products.get(id)`            | `Promise<Product>`                      |
| `create` | `pocketsflow.products.create(params)`     | `Promise<Product>`                      |
| `update` | `pocketsflow.products.update(id, params)` | `Promise<Product>`                      |
| `delete` | `pocketsflow.products.delete(id)`         | `Promise<{ message: string }>`          |
| `copy`   | `pocketsflow.products.copy(id, params?)`  | `Promise<Product \| SubscriptionOffer>` |

```ts theme={null}
const product = await pocketsflow.products.create({
  name: "Premium Course",
  price: 49.99,
  description: "A self-paced course.",
});

await pocketsflow.products.update(product._id, {
  name: "Premium Course — Updated",
  price: 59.99,
});
```

`copy` duplicates a one-time product or a subscription offer, whichever owns the id. Pass `{ testMode: false }` to copy a test-mode item into live mode; omit params to copy within the source's own mode. The copy is named "Name (Copy)" and starts unpublished when copied into live mode.

```ts theme={null}
const liveCopy = await pocketsflow.products.copy(product._id, {
  testMode: false,
});
```

### `CreateProductParams`

| Property                      | Type       | Required | Description                                                           |
| ----------------------------- | ---------- | -------- | --------------------------------------------------------------------- |
| `name`                        | `string`   | Yes      | Product name.                                                         |
| `price`                       | `number`   | Yes      | Product price.                                                        |
| `description`                 | `string`   | No       | Product description.                                                  |
| `subtitle`                    | `string`   | No       | Short product subtitle.                                               |
| `payWant`                     | `boolean`  | No       | Enable pay-what-you-want pricing.                                     |
| `minPrice`, `maxPrice`        | `number`   | No       | Bounds for pay-what-you-want pricing.                                 |
| `published`                   | `boolean`  | No       | Whether the product is published.                                     |
| `slug`                        | `string`   | No       | Product URL slug.                                                     |
| `thumbnail`                   | `string`   | No       | Thumbnail URL.                                                        |
| `images`                      | `string[]` | No       | Product image URLs.                                                   |
| `showSales`, `showReviews`    | `boolean`  | No       | Whether sales and reviews are shown.                                  |
| `refundPolicy`                | `string`   | No       | ID of a refund policy (see [Refunds](#refunds)), not the policy text. |
| `hasFirstName`, `hasLastName` | `boolean`  | No       | Collect buyer name fields at checkout.                                |

`update(id, params)` accepts the editable product fields: `name`, `description`, `price`, `currency`, `active`, and `published`.

## Product variants

| Method   | Signature                             | Returns                        |
| -------- | ------------------------------------- | ------------------------------ |
| `create` | `pocketsflow.variants.create(params)` | `Promise<ProductVariant>`      |
| `delete` | `pocketsflow.variants.delete(id)`     | `Promise<{ message: string }>` |

```ts theme={null}
const variant = await pocketsflow.variants.create({
  productId: product._id,
  name: "Video + workbook",
  price: 79.99,
});
```

`CreateVariantParams` requires `productId`, `name`, and `price`; `description` is optional.

## Orders

| Method | Signature                          | Returns                   |
| ------ | ---------------------------------- | ------------------------- |
| `list` | `pocketsflow.orders.list(params?)` | `Promise<OrdersResponse>` |
| `get`  | `pocketsflow.orders.get(id)`       | `Promise<Order>`          |

`ListOrdersParams` supports `productId`, `startDate`, `endDate`, `page`, and `pageSize`. The date filter applies only when you pass **both** `startDate` and `endDate`; one bound on its own is ignored. `OrdersResponse` contains `orders` and a `pagination` object.

```ts theme={null}
const result = await pocketsflow.orders.list({
  page: 1,
  pageSize: 20,
  startDate: "2026-01-01",
  endDate: "2026-01-31",
  productId: product._id,
});
```

## Customers

| Method | Signature                             | Returns               |
| ------ | ------------------------------------- | --------------------- |
| `list` | `pocketsflow.customers.list(params?)` | `Promise<Customer[]>` |
| `get`  | `pocketsflow.customers.get(id)`       | `Promise<Customer>`   |

The API applies `productId`, `sortBy`, and `sortOrder` from `ListCustomersParams`. `sortBy` is `email`, `country`, `numberOfOrders`, or `createdAt`; `sortOrder` is `asc` or `desc`. The list is not paginated: it always returns every matching customer.

<Warning>
  `ListCustomersParams` also types `email`, `limit`, and `offset`, but the API
  ignores them today. Filter or page the returned array in your own code.
</Warning>

## Reviews

| Method | Signature                           | Returns             |
| ------ | ----------------------------------- | ------------------- |
| `list` | `pocketsflow.reviews.list(params?)` | `Promise<Review[]>` |

`list()` returns every review across your products.

<Warning>
  `ListReviewsParams` types an optional `productId`, but `GET /reviews` ignores
  it and returns every review. Filter by `productId` on the returned array.
</Warning>

```ts theme={null}
const reviews = (await pocketsflow.reviews.list()).filter(
  (review) => review.productId === product._id
);
```

## Discounts

| Method   | Signature                                  | Returns                        |
| -------- | ------------------------------------------ | ------------------------------ |
| `list`   | `pocketsflow.discounts.list()`             | `Promise<Discount[]>`          |
| `get`    | `pocketsflow.discounts.get(id)`            | `Promise<Discount>`            |
| `create` | `pocketsflow.discounts.create(params)`     | `Promise<Discount>`            |
| `update` | `pocketsflow.discounts.update(id, params)` | `Promise<Discount>`            |
| `delete` | `pocketsflow.discounts.delete(id)`         | `Promise<{ message: string }>` |

```ts theme={null}
const discount = await pocketsflow.discounts.create({
  name: "Launch discount",
  code: "LAUNCH20",
  value: 20,
  valueType: "percentage",
  mainProductIds: [product._id],
});
```

`CreateDiscountParams` requires `name`, `code`, `value`, and `mainProductIds`. `valueType` is `percentage` or `fixed`; `active` is optional. The update type makes all fields optional.

<Warning>
  The SDK types also accept `expiration`, but the API does not store it on
  create or update, so the discount stays valid until you deactivate or delete
  it. Set `active: false` when a promotion ends.
</Warning>

## Upsells

| Method   | Signature                                | Returns                        |
| -------- | ---------------------------------------- | ------------------------------ |
| `list`   | `pocketsflow.upsells.list()`             | `Promise<UpsellsResponse>`     |
| `get`    | `pocketsflow.upsells.get(id)`            | `Promise<Upsell>`              |
| `create` | `pocketsflow.upsells.create(params)`     | `Promise<Upsell>`              |
| `update` | `pocketsflow.upsells.update(id, params)` | `Promise<Upsell>`              |
| `delete` | `pocketsflow.upsells.delete(id)`         | `Promise<{ message: string }>` |

`CreateUpsellParams` requires `mainProductIds`, `upsellProductId`, and `upsellPrice`. Optional fields include `name`, `offer`, `upsellDescription`, `primaryButtonText`, `secondaryButtonText`, and `active`.

## Subscription offers

Subscription offers are the recurring products you sell. They are distinct from buyer subscriptions in the `subscriptions` namespace.

| Method   | Signature                                       | Returns                        |
| -------- | ----------------------------------------------- | ------------------------------ |
| `list`   | `pocketsflow.subscriptionOffers.list()`         | `Promise<SubscriptionOffer[]>` |
| `get`    | `pocketsflow.subscriptionOffers.get(id)`        | `Promise<SubscriptionOffer>`   |
| `create` | `pocketsflow.subscriptionOffers.create(params)` | `Promise<SubscriptionOffer>`   |

```ts theme={null}
const offer = await pocketsflow.subscriptionOffers.create({
  name: "Pro Membership",
  price: 29,
  frequency: "monthly",
  trialPeriod: 7,
});
```

### `CreateSubscriptionOfferParams`

| Property                                                                                                   | Type                          | Required | Description                                |
| ---------------------------------------------------------------------------------------------------------- | ----------------------------- | -------- | ------------------------------------------ |
| `name`                                                                                                     | `string`                      | Yes      | Offer name.                                |
| `price`                                                                                                    | `number`                      | Yes      | Recurring price in USD.                    |
| `frequency`                                                                                                | `weekly \| monthly \| yearly` | Yes      | Billing interval.                          |
| `subtitle`, `description`                                                                                  | `string`                      | No       | Offer copy.                                |
| `trialPeriod`                                                                                              | `number`                      | No       | Trial duration in days.                    |
| `published`                                                                                                | `boolean`                     | No       | Whether the offer is published.            |
| `redirectBackUrl`, `slug`                                                                                  | `string`                      | No       | Billing portal return URL and offer slug.  |
| `thumbnail`                                                                                                | `string`                      | No       | Thumbnail URL.                             |
| `images`                                                                                                   | `string[]`                    | No       | Offer image URLs.                          |
| `isFile`, `hasFirstName`, `hasLastName`, `hasProductPage`, `showSales`, `showReviews`, `hasCallbackUrl`    | `boolean`                     | No       | Offer and checkout behavior flags.         |
| `file`, `url`, `callbackUrl`                                                                               | `string \| object`            | No       | File, external URL, and callback settings. |
| `checkoutText`, `portalText`, `privacyPolicy`, `termsOfService`, `refundPolicy`, `ctaText`, `thankYouText` | `string`                      | No       | Checkout, portal, and policy copy.         |
| `maxPrice`, `minPrice`                                                                                     | `number`                      | No       | Pay-what-you-want bounds.                  |
| `design`, `colors`, `pageStyle`, `checkoutStyle`, `checkoutColors`                                         | `Record<string, unknown>`     | No       | Advanced presentation configuration.       |

`frequency` must be `weekly`, `monthly`, or `yearly`.

## Buyer subscriptions

The `subscriptions` namespace manages buyer memberships. Use `subscriptionOffers` to manage the recurring products themselves.

| Method   | Signature                                                | Returns                        |
| -------- | -------------------------------------------------------- | ------------------------------ |
| `list`   | `pocketsflow.subscriptions.list(params?)`                | `Promise<any>`                 |
| `get`    | `pocketsflow.subscriptions.get(id)`                      | `Promise<Subscription>`        |
| `cancel` | `pocketsflow.subscriptions.cancel(stripeSubscriptionId)` | `Promise<{ message: string }>` |
| `refund` | `pocketsflow.subscriptions.refund(stripeSubscriptionId)` | `Promise<{ message: string }>` |

<Warning>
  `cancel` and `refund` call legacy routes keyed by a Stripe subscription id
  (`sub_…`). Current subscriptions don't carry one, so these calls return `404`.
  To cancel (at period end), pause, or resume a subscriber, call [`POST
      /subscriptions/{id}/cancel`](/api-reference/endpoints#subscriptions) (or
  `/pause`, `/resume`) with the subscriber `_id` or membership id (`mem_…`).
  Issue refunds from the dashboard.
</Warning>

`ListSubscriptionsParams` supports `status`, `startDate`, `endDate`, `page`, and `pageSize`. The current SDK list method uses the legacy subscription-customer endpoint; the canonical REST subscriber catalog is [`GET /subscriptions/subscribers`](/api-reference/endpoints#subscriptions).

## Webhooks

| Method   | Signature                                 | Returns                        |
| -------- | ----------------------------------------- | ------------------------------ |
| `list`   | `pocketsflow.webhooks.list()`             | `Promise<Webhook[]>`           |
| `get`    | `pocketsflow.webhooks.get(id)`            | `Promise<Webhook>`             |
| `create` | `pocketsflow.webhooks.create(params)`     | `Promise<Webhook>`             |
| `update` | `pocketsflow.webhooks.update(id, params)` | `Promise<Webhook>`             |
| `delete` | `pocketsflow.webhooks.delete(id)`         | `Promise<{ message: string }>` |
| `test`   | `pocketsflow.webhooks.test(id)`           | `Promise<{ message: string }>` |

```ts theme={null}
const webhook = await pocketsflow.webhooks.create({
  url: "https://example.com/webhooks/pocketsflow",
  events: ["order.completed", "invoice.payment_succeeded"],
  description: "Order and billing events",
});

await pocketsflow.webhooks.test(webhook._id);
```

`CreateWebhookParams` requires an HTTPS `url` and an `events` array. The SDK exports the `WebhookEvent` union for typed event names.

<Warning>
  The current SDK `webhooks.update` implementation uses `PUT`, while the public
  REST endpoint is `PATCH /webhooks/{id}`. Use the REST endpoint for updates
  until the SDK method is aligned in a follow-up release.
</Warning>

## Users

| Method   | Signature                          | Returns         |
| -------- | ---------------------------------- | --------------- |
| `me`     | `pocketsflow.users.me()`           | `Promise<User>` |
| `update` | `pocketsflow.users.update(params)` | `Promise<User>` |

`UpdateUserParams` supports `firstName`, `lastName`, `currency`, `country`, `subdomain`, and `contactEmail`.

## Checkout

Create a hosted checkout session for either a one-time product or a subscription offer.

```ts theme={null}
const session = await pocketsflow.checkout.create({
  productId: offer._id,
  successUrl: "https://example.com/success",
  cancelUrl: "https://example.com/cancel",
  customerEmail: "buyer@example.com",
  discountCode: "LAUNCH20",
  metadata: { source: "pricing-page" },
});

console.log(session.url);
```

`CreateCheckoutParams` requires `productId`, `successUrl`, and `cancelUrl`. Optional fields are `customerEmail`, `discountCode`, and `metadata`.

## Refunds

| Method   | Signature                            | Returns             |
| -------- | ------------------------------------ | ------------------- |
| `list`   | `pocketsflow.refunds.list()`         | `Promise<Refund[]>` |
| `get`    | `pocketsflow.refunds.get(id)`        | `Promise<Refund>`   |
| `create` | `pocketsflow.refunds.create(params)` | `Promise<Refund>`   |

The API behind `refunds` manages **refund policies**: the terms shown to buyers at checkout, which products reference by id (`refundPolicy`). A policy has `name`, `policy` (the text), `period`, and `periodType` (`days` or `weeks`).

<Warning>
  The SDK's `Refund` / `CreateRefundParams` types describe order refunds
  (`orderId`, `amount`, `reason`). The API does not process them: those fields
  are dropped and no payment is refunded. Refund a payment from the dashboard.
  Use `list()` and `get(id)` to read your refund policies.
</Warning>

## Errors

Failed requests reject with `PocketsflowError`:

```ts theme={null}
import { Pocketsflow, PocketsflowError } from "pocketsflow";

try {
  await pocketsflow.products.get("missing_product");
} catch (error) {
  if (error instanceof PocketsflowError) {
    console.error(error.message, error.status, error.code);
  }
}
```

| Property  | Type                  | Description                               |
| --------- | --------------------- | ----------------------------------------- |
| `message` | `string`              | Human-readable error message.             |
| `status`  | `number \| undefined` | HTTP status code, when available.         |
| `code`    | `string \| undefined` | API or client error code, when available. |

The SDK also maps request timeouts to a `PocketsflowError` with code `TIMEOUT`.

## TypeScript types

The package exports the request and response types used by every method, including `Product`, `Order`, `Customer`, `SubscriptionOffer`, `Webhook`, `CheckoutSession`, `Refund`, and all `Create*Params`, `Update*Params`, and list parameter types. Import them as type-only imports:

```ts theme={null}
import type {
  CreateProductParams,
  Product,
  SubscriptionOffer,
} from "pocketsflow";
```

For the corresponding HTTP operation, request body, response codes, and full schema, see the [REST endpoint reference](/api-reference/endpoints) or open the [interactive API explorer](https://api.pocketsflow.com/docs).
