npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@oaknetwork/payments-sdk

v1.1.0

Published

A fully-typed TypeScript SDK for the Oak Network payment API.

Readme

Oak Payments SDK

A fully-typed TypeScript SDK for the Oak Network Payments API. Drop-in authentication, automatic retries, and zero boilerplate, production-ready from day one.

Full documentation - oaknetwork.org/docs/sdk/overview

Getting credentials

To use the SDK you need a Client ID and Client Secret. Contact [email protected] to get your sandbox credentials.

Create a .env file in your project root:

CLIENT_ID=your-client-id
CLIENT_SECRET=your-client-secret

Install dotenv to load these automatically: pnpm add dotenv, then add import 'dotenv/config' at the top of your entry file.

| Variable | Required | Description | | --------------- | -------- | --------------------------- | | CLIENT_ID | Yes | Your merchant client ID | | CLIENT_SECRET | Yes | Your merchant client secret |

Use different credentials for sandbox and production. Never commit .env files or log secrets.


Quick start

Installation

pnpm add @oaknetwork/payments-sdk
# or
npm install @oaknetwork/payments-sdk
# or
yarn add @oaknetwork/payments-sdk

Requirements: Node.js 18+, TypeScript 5.x recommended.

Basic usage

import "dotenv/config";
import {
  createOakClient,
  createCustomerService,
} from "@oaknetwork/payments-sdk";

const client = createOakClient({
  environment: "sandbox",
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
});

const customers = createCustomerService(client);

const result = await customers.list();

if (result.ok) {
  console.log(result.value.data);
} else {
  console.error(result.error.message);
}

See the full Quickstart guide for a step-by-step walkthrough.


Services

The SDK ships 10 service modules. Import the factory function for each service you need.

| Service | Factory | What it does | | ---------------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------- | | Customers | createCustomerService(client) | Create, get, list, update, sync, and check balances | | Payments | createPaymentService(client) | Create, confirm, cancel payments | | Payment Methods | createPaymentMethodService(client) | Add, list, get, delete payment methods | | Webhooks | createWebhookService(client) | Register, manage, and monitor webhooks | | Transactions | createTransactionService(client) | List, get, and settle transactions | | Transfers | createTransferService(client) | Create provider transfers (Stripe, PagarMe, BRLA) | | Plans | createPlanService(client) | CRUD subscription plans | | Refunds | createRefundService(client) | Refund a payment (full or partial) | | Buy | createBuyService(client) | Crypto on-ramp via Bridge | | Sell | createSellService(client) | Crypto off-ramp via Avenia |


Usage examples

Customers

import { createCustomerService } from "@oaknetwork/payments-sdk";

const customers = createCustomerService(client);

// Create
const result = await customers.create({
  email: "[email protected]",
  first_name: "John",
  last_name: "Doe",
  country_code: "US",
});

// List
await customers.list({ limit: 10, offset: 0 });

// Get
await customers.get("customer_id");

// Update
await customers.update("customer_id", { email: "[email protected]" });

Providers

import { createProviderService } from "@oaknetwork/payments-sdk";

const providers = createProviderService(client);

// Register as Stripe customer (buyer)
await providers.submitRegistration(customerId, {
  provider: "stripe",
  target_role: "customer",
});

// Register as Stripe connected account (seller)
await providers.submitRegistration(customerId, {
  provider: "stripe",
  target_role: "connected_account",
  provider_data: {
    account_type: "express",
    transfers_requested: true,
    card_payments_requested: true,
    tax_reporting_us_1099_k_requested: false,
    payouts_debit_negative_balances: false,
    external_account_collection_requested: false,
  },
});

// Check registration status
const status = await providers.getRegistrationStatus(customerId);

Payments

import { createPaymentService } from "@oaknetwork/payments-sdk";

const payments = createPaymentService(client);

// Create and capture a payment
const result = await payments.create({
  provider: "stripe",
  source: {
    amount: 5000,
    currency: "usd",
    customer: { id: customerId },
    payment_method: { type: "card", id: paymentMethodId },
    capture_method: "automatic",
  },
  confirm: true,
});

// Confirm / cancel
await payments.confirm("payment_id");
await payments.cancel("payment_id");

Payment methods

import { createPaymentMethodService } from "@oaknetwork/payments-sdk";

const paymentMethods = createPaymentMethodService(client);

// Add a card
await paymentMethods.add(customerId, {
  type: "card",
  provider: "stripe",
});

// Add a bank account
await paymentMethods.add(customerId, {
  type: "bank",
  provider: "stripe",
  currency: "usd",
  bank_name: "Chase",
  bank_account_number: "000123456789",
  bank_routing_number: "021000021",
  bank_account_type: "checking",
  bank_account_name: "John Doe",
});

// List / get / delete
await paymentMethods.list(customerId);
await paymentMethods.get(customerId, "pm_id");
await paymentMethods.delete(customerId, "pm_id");

Transfers

import { createTransferService } from "@oaknetwork/payments-sdk";

const transfers = createTransferService(client);

await transfers.create({
  provider: "stripe",
  source: {
    amount: 1000,
    currency: "usd",
    customer: { id: customerId },
  },
  destination: {
    customer: { id: customerId },
    payment_method: { type: "bank", id: bankPmId },
  },
});

Refunds

import { createRefundService } from "@oaknetwork/payments-sdk";

const refunds = createRefundService(client);

// Full refund
await refunds.create(paymentId, {});

// Partial refund
await refunds.create(paymentId, { amount: 500 });

Plans

import { createPlanService } from "@oaknetwork/payments-sdk";

const plans = createPlanService(client);

await plans.create({
  name: "Pro Plan",
  description: "Monthly pro subscription",
  price: 2999,
  currency: "USD",
  frequency: 30,
  start_date: "2026-03-01",
  is_auto_renewable: true,
  allow_amount_override: false,
  created_by: customerId,
});

await plans.list();
await plans.details("plan_id");

Transactions

import { createTransactionService } from "@oaknetwork/payments-sdk";

const transactions = createTransactionService(client);

await transactions.list({ limit: 20 });
await transactions.get("txn_id");

Webhooks

Register endpoints to receive real-time event notifications, and verify incoming payloads with HMAC-SHA256 signature verification.

import {
  createWebhookService,
  verifyWebhookSignature,
  parseWebhookPayload,
} from "@oaknetwork/payments-sdk";

const webhooks = createWebhookService(client);

// Register
const wh = await webhooks.register({
  url: "https://your-server.com/webhooks/oak",
  description: "Payment events",
});

if (wh.ok) {
  console.log("Secret:", wh.value.data.secret); // store securely
}

// List / update / delete
await webhooks.list();
await webhooks.update("webhook_id", { url: "https://new-url.com/webhooks" });
await webhooks.toggle("webhook_id");
await webhooks.delete("webhook_id");

Verify and parse incoming events

import { parseWebhookPayload } from "@oaknetwork/payments-sdk";
import express from "express";

const app = express();

app.post(
  "/webhooks/oak",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const result = parseWebhookPayload(
      req.body.toString(),
      req.headers["x-oak-signature"] as string,
      process.env.WEBHOOK_SECRET!,
    );

    if (!result.ok) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    switch (result.value.event) {
      case "payment.succeeded":
        break;
      case "payment.failed":
        break;
      case "provider_registration.approved":
        break;
    }

    res.json({ received: true });
  },
);

Full webhook reference — oaknetwork.org/docs/sdk/webhooks


Error handling

Every method returns Result<T, OakError> — no uncaught exceptions. Check result.ok to branch on success or failure.

const result = await customers.create({
  email: "[email protected]",
  first_name: "John",
});

if (result.ok) {
  const customer = result.value.data;
  console.log("Created:", customer.id);
} else {
  console.error("Failed:", result.error.message);
  console.error("Status:", result.error.statusCode);
  console.error("Code:", result.error.code);
}

| Error type | Description | | --------------------------- | ---------------------------------------- | | ApiError | HTTP errors from the API (4xx, 5xx) | | NetworkError | Network failures, timeouts | | ParseError | Invalid JSON responses | | AbortError | Request aborted | | EnvironmentViolationError | Sandbox-only method called in production |

Full error handling guide — oaknetwork.org/docs/sdk/error-handling


Configuration

Environments

| Environment | API Base URL | Description | | ------------ | ----------------------------------- | -------------------------------- | | sandbox | https://api-stage.usecrowdpay.xyz | Testing — all operations allowed | | production | https://app.usecrowdpay.xyz | Live — test operations blocked |

const client = createOakClient({
  environment: "sandbox",
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,

  // Optional: point to a custom API server
  customUrl: "https://my-dev-server.example.com",
});

Retry configuration

The SDK automatically retries failed requests with exponential backoff and jitter.

const client = createOakClient({
  environment: "sandbox",
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  retryOptions: {
    maxNumberOfRetries: 3,
    delay: 1000,
    backoffFactor: 2,
    maxDelay: 30000,
  },
});

Retried status codes: 408, 429, 500, 502, 503, 504.


TypeScript support

The SDK ships full type declarations. All service methods, request payloads, and responses are typed.

import type { Result } from "@oaknetwork/payments-sdk";

Development

Package manager

This project uses pnpm exclusively:

pnpm install          # Install dependencies
pnpm build            # Build all packages
pnpm test             # Run tests
pnpm lint             # Lint code

Do not use npm or yarn. The repository enforces pnpm >= 10.0.0.

Running tests

pnpm test:unit          # Unit tests
pnpm test:integration   # Integration tests (requires credentials)
pnpm test:all           # All tests with coverage
pnpm test:watch         # Watch mode

Changesets workflow

We use Changesets to manage versions and changelogs:

  1. After making changes, run pnpm changeset
  2. Select impact (Major / Minor / Patch) for affected packages
  3. Commit the generated file in .changeset/
  4. CI automatically calculates versions, generates changelogs, and creates a release PR

Code coverage

Coverage is reported to Codecov after each successful CI run.

Development guidelines

See CLAUDE.md for coding standards including architecture principles, security rules, testing requirements, and anti-patterns.

Code review checklist

  • [ ] pnpm build succeeds
  • [ ] pnpm test passes with >90% coverage
  • [ ] pnpm lint has no errors
  • [ ] Changeset created with pnpm changeset
  • [ ] Documentation updated if needed

Documentation


License

MIT

Security

Security Policy

Links


Questions? Open an issue or contact [email protected]