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

paystack-sdk-node

v0.8.0

Published

Type-safe, modern TypeScript SDK for the Paystack API. Includes first-class support for Express, NestJS, Next.js, and Fastify.

Readme

paystack-sdk-node

Type-safe, modern TypeScript SDK for the Paystack API.

This package helps you talk to Paystack from Node.js, with:

  • A PaystackClient that wraps the core REST API
  • First-class resource classes (customers, transactions, transfers, DVAs, etc.)
  • Webhook signature verification utilities
  • Framework helpers for Express, NestJS, and Next.js

This SDK is not an official Paystack product.


Installation

# with bun
bun add paystack-sdk-node

# or with npm
npm install paystack-sdk-node

# or with pnpm
pnpm add paystack-sdk-node

This library targets modern runtimes:

  • Node.js 18+ or Bun
  • TypeScript 5+ (types included)

Quick start

Create a client

import { PaystackClient } from 'paystack-sdk'

const client = new PaystackClient({
  apiKey: process.env.PAYSTACK_SECRET_KEY!,
})

You can optionally override:

  • baseUrl (defaults to https://api.paystack.co)
  • maxRetries (defaults to 3)
  • fetchImpl (custom fetch for environments without global fetch)

You can also create a client from environment variables using createPaystackClient, which reads standard config keys from your environment:

import { createPaystackClient } from '@samaasi/paystack-sdk'

const client = await createPaystackClient()

Core resources

The client exposes strongly-typed resource helpers under client.*.

Customers

// Create customer
const created = await client.customers.create({
  email: '[email protected]',
  first_name: 'Ada',
  last_name: 'Lovelace',
})

// List customers
const list = await client.customers.list({ perPage: 20, page: 1 })

// Update customer
await client.customers.update(created.data.customer_code, {
  phone: '+2348000000000',
})

Transactions

// Initialize a transaction
const tx = await client.transactions.initialize({
  email: '[email protected]',
  amount: 20000, // amount in kobo
})

// Verify a transaction
const verified = await client.transactions.verify(tx.data.reference)

Apple Pay

Manage Apple Pay domains for your integration.

// Register a domain
await client.applePay.registerDomain({
  domainName: 'example.com',
})

// List registered domains
const domains = await client.applePay.listDomains()

// Unregister a domain
await client.applePay.unregisterDomain({
  domainName: 'example.com',
})

Webhooks

The SDK provides helper functions and an event enum to make handling webhooks type-safe and secure.

import { PaystackEvent } from 'paystack-sdk/enums'

// Check if an event string matches a known Paystack event
if (event === PaystackEvent.ChargeSuccess) {
  // Handle successful charge
}

Framework Integrations

Express

import { createPaystackExpressMiddleware } from 'paystack-sdk/express'

app.post(
  '/webhook',
  createPaystackExpressMiddleware({
    secretKey: process.env.PAYSTACK_SECRET_KEY!,
  }),
  (req, res) => {
    const event = req.paystackEvent
    // Handle event...
    res.sendStatus(200)
  },
)

Next.js (App Router)

import { verifyPaystackNextjsRequest } from 'paystack-sdk/nextjs'

export async function POST(req: Request) {
  const { valid, event } = await verifyPaystackNextjsRequest(req, {
    secretKey: process.env.PAYSTACK_SECRET_KEY!,
  })

  if (!valid) return new Response('Invalid signature', { status: 401 })

  // Handle event...
  return new Response('OK', { status: 200 })
}

Fastify

import { createPaystackFastifyHook } from 'paystack-sdk/fastify'

fastify.post(
  '/webhook',
  {
    preValidation: createPaystackFastifyHook({
      secretKey: process.env.PAYSTACK_SECRET_KEY!,
    }),
  },
  async (req, reply) => {
    const event = req.paystackEvent
    // Handle event...
    return { status: 'success' }
  },
)

Transfers and recipients

// Create a transfer recipient
const recipient = await client.transferRecipients.create({
  type: 'nuban',
  name: 'Jane Doe',
  account_number: '0123456789',
  bank_code: '058',
  currency: 'NGN',
})

// Initiate a transfer
const transfer = await client.transfers.initiate(
  {
    source: 'balance',
    amount: 100000, // 1000 NGN in kobo
    recipient: recipient.data.recipient_code,
    reference: 'salary-2025-01-01',
  },
  { idempotencyKey: 'salary-2025-01-01' },
)

Verification (bank + BVN)

// Resolve bank account name
const resolved = await client.verification.resolveAccount({
  account_number: '0123456789',
  bank_code: '058',
})

// Match BVN to bank account
const match = await client.verification.matchBvn({
  account_number: '0123456789',
  bank_code: '058',
  bvn: '12345678901',
})

Subaccounts and subscriptions

// Create a subaccount
const sub = await client.subaccounts.create({
  business_name: 'Acme Partners',
  settlement_bank: '058',
  account_number: '0123456789',
  percentage_charge: 20,
})

// Create a subscription
const subscription = await client.subscriptions.create({
  customer: 'CUS_xxxxxxxx',
  plan: 'PLN_xxxxxxxx',
})

Dedicated Virtual Accounts (DVAs)

const dva = await client.virtualAccounts.create({
  customer: 'CUS_xxxxxxxx',
  preferred_bank: 'titan-paystack',
})

Webhooks

The SDK provides low-level signature helpers and some framework-specific utilities.

Signature verification

Subpath: paystack-sdk/webhooks

import { verifyPaystackSignature } from 'paystack-sdk/webhooks'

const valid = await verifyPaystackSignature({
  payload: rawBody, // string or Uint8Array
  signature: req.headers['x-paystack-signature'] as string | undefined,
  secretKey: process.env.PAYSTACK_SECRET_KEY!,
})

Type-safe events

Subpath: root resources

import { isWebhookEvent, type WebhookEvent } from 'paystack-sdk'

if (isWebhookEvent(body)) {
  const event: WebhookEvent = body

  if (event.event === 'charge.success') {
    // handle successful charge
  }
}

Framework integrations

Express

Subpath: paystack-sdk/express

import express from 'express'
import { createPaystackExpressMiddleware } from 'paystack-sdk/express'

const app = express()

app.post(
  '/webhooks/paystack',
  createPaystackExpressMiddleware({
    secretKey: process.env.PAYSTACK_SECRET_KEY!,
  }),
  (req, res) => {
    const event = (req as any).paystackEvent
    // handle event
    res.sendStatus(200)
  },
)

Ensure your Express setup preserves the raw request body (for example by using a body parser that keeps req.rawBody, or by wiring a raw-body middleware).

NestJS

Subpath: paystack-sdk/nestjs

import { Controller, Post, Req, UseGuards } from '@nestjs/common'
import { PaystackWebhookGuard } from 'paystack-sdk/nestjs'

@Controller('webhooks/paystack')
@UseGuards(
  new PaystackWebhookGuard({
    secretKey: process.env.PAYSTACK_SECRET_KEY!,
  }),
)
export class PaystackWebhookController {
  @Post()
  handle(@Req() req: any) {
    const event = req.body
    // handle event
    return 'ok'
  }
}

Next.js (App Router)

Subpath: paystack-sdk/nextjs

// app/api/webhooks/paystack/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { verifyPaystackNextjsRequest } from 'paystack-sdk/nextjs'

export async function POST(req: NextRequest) {
  const { valid, event } = await verifyPaystackNextjsRequest(req, {
    secretKey: process.env.PAYSTACK_SECRET_KEY!,
  })

  if (!valid) {
    return new NextResponse('Invalid signature', { status: 401 })
  }

  // handle event
  return new NextResponse('ok')
}

Idempotency

The SDK includes helpers for idempotent requests via the x-idempotency-key header.

import { generateIdempotencyKey, withIdempotencyKey } from 'paystack-sdk'

const key = generateIdempotencyKey()

const init = withIdempotencyKey(
  {
    method: 'POST',
    body: JSON.stringify({}),
  },
  key,
)

Core resources that support idempotency (for example transfers) accept an idempotencyKey option and apply it internally.


Development

Install dependencies:

bun install

Build the library:

bun run build

Run tests (if present):

bun test

Formatting:

  • Use bun format locally for fast formatting during development.
  • Run ESLint in CI (GitHub Actions) before releases to enforce consistency.

License

This project is licensed under the MIT License. See LICENSE for details.