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

apibill-billing-sdk

v1.1.4

Published

JavaScript/TypeScript SDK for ApiBill Client API — billing info, invoices, payments, and restriction middleware for admin panels

Readme

@nextive/billing-sdk

JavaScript/TypeScript SDK for ApiBill Client API. Embed billing info, invoices, payments, and restriction middleware into any admin panel.

Works with Nuxt 3/4, Vue 3 + Vuetify, React, or any JavaScript project.

Installation

# npm
npm install @nextive/billing-sdk

# yarn
yarn add @nextive/billing-sdk

# Or install from git
npm install git+https://github.com/Nextive-Solution/apibill-js-sdk.git

Quick Start

import { ApiBillClient } from '@nextive/billing-sdk'

const billing = new ApiBillClient({
  siteId: 'YOUR_SITE_ID',
  apiUrl: 'https://your-api.com/api',
})

// Get billing summary
const summary = await billing.getBillingSummary()
console.log(summary.billing.totalDue)        // 5225.32
console.log(summary.billing.restrictionActive) // true/false

// Check restriction
const blocked = await billing.isRestricted()

// List unpaid invoices
const invoices = await billing.getInvoices('unpaid')

// Pay an invoice (redirects to bKash)
const { gatewayUrl } = await billing.payInvoice('invoice_id')
window.location.href = gatewayUrl

API Reference

new ApiBillClient(config)

| Option | Type | Required | Description | |---|---|---|---| | siteId | string | Yes | Your Site ID from ApiBill admin panel | | apiUrl | string | Yes | ApiBill API base URL (e.g. https://your-api.com/api) | | fetch | typeof fetch | No | Custom fetch implementation (defaults to global fetch) | | onRestriction | (summary) => void | No | Called when restrictionActive is true | | cacheTtl | number | No | Cache TTL in ms for billing summary (default: 300000 = 5 min) |

Methods

Billing Summary

// Get full billing summary (cached for cacheTtl)
const summary = await billing.getBillingSummary()

// Force refresh (skip cache)
const fresh = await billing.getBillingSummary(true)

// Check if restricted (shorthand)
const restricted = await billing.isRestricted() // boolean

// Check restriction + trigger onRestriction callback
const restricted = await billing.checkRestriction() // boolean

// Clear cache manually
billing.clearCache()

Invoices

// List all invoices (paid + unpaid + partially_paid)
const all = await billing.getInvoices()

// Filter by status
const unpaid = await billing.getInvoices('unpaid')
const paid = await billing.getInvoices('paid')
const partial = await billing.getInvoices('partially_paid')

// Get single invoice
const invoice = await billing.getInvoice('invoice_id')
console.log(invoice.invoiceNumber)  // 'NS0010001'
console.log(invoice.paidAmount)     // 2000
console.log(invoice.dueAmount)      // 3000
console.log(invoice.payments)       // PaymentRecord[]

// Get last unpaid/partially paid invoice
const lastUnpaid = await billing.getLastUnpaidInvoice()

// Pay full due amount via bKash
const { gatewayUrl, paymentId, type } = await billing.payInvoice('invoice_id')
window.location.href = gatewayUrl

// Pay a specific pending payment (partial amount set by admin)
const pending = invoice.payments.find(p => p.status === 'pending')
if (pending) {
  const { gatewayUrl } = await billing.payInvoice('invoice_id', pending.paymentId)
  window.location.href = gatewayUrl
}

Bank Transfer Notifications

// Notify admin that a bank transfer payment has been initiated.
// Sends an email + in-app notification to all admins so they can
// verify the transfer against their bank account and mark the invoice paid.

// For a regular invoice (default type)
await billing.notifyBankTransfer('invoice_id')

// For a custom invoice
await billing.notifyBankTransfer('custom_invoice_id', 'custom_invoice')

Use this after displaying bank account details to the client so the admin is proactively alerted instead of having to poll their bank account.

Custom Invoices

// List custom invoices
const custom = await billing.getCustomInvoices()
const unpaidCustom = await billing.getCustomInvoices('unpaid')
const partialCustom = await billing.getCustomInvoices('partially_paid')

// Get single custom invoice
const invoice = await billing.getCustomInvoice('custom_invoice_id')
console.log(invoice.invoiceNumber) // 'NS0010006'
console.log(invoice.paidAmount)    // 5000
console.log(invoice.dueAmount)     // 10000

// Pay full due via bKash
const { gatewayUrl } = await billing.payCustomInvoice('custom_invoice_id')
window.location.href = gatewayUrl

// Pay a specific pending payment
const pending = invoice.payments.find(p => p.status === 'pending')
if (pending) {
  const { gatewayUrl } = await billing.payCustomInvoice('custom_invoice_id', pending.paymentId)
  window.location.href = gatewayUrl
}

Response Types

BillingSummaryResponse

{
  site: { _id: string, domain: string }
  client: { name: string, email: string, phone: string | null } | null
  plan: {
    freeTier: number
    ratePerThousand: number
    bandwidthRatePerGb: number
    bandwidthFreeTierGb: number
    serviceCharge: number
    maintenanceCharge: number
    currency: string
  } | null
  billing: {
    totalDue: number              // Combined due from invoices + custom invoices
    totalPaid: number             // Total already paid across partial invoices
    currency: string
    unpaidCount: number
    partiallyPaidCount: number    // Number of partially paid invoices
    restrictedCount: number       // Number of restricted unpaid invoices
    flexibleCount: number         // Number of flexible unpaid invoices
    restrictionActive: boolean    // true = block admin panel access
  }
  invoices: {
    totalDue: number
    unpaidCount: number
    nextDueDate: string | null
    unpaid: UnpaidInvoice[]
  }
  customInvoices: {
    totalDue: number
    unpaidCount: number
    nextDueDate: string | null
    unpaid: UnpaidCustomInvoice[]
  }
}

Error Handling

import { ApiBillError } from '@nextive/billing-sdk'

try {
  await billing.payInvoice('id')
} catch (err) {
  if (err instanceof ApiBillError) {
    console.log(err.statusCode) // 400, 404, etc.
    console.log(err.response)   // API response body
  }
}

Framework Integration

Nuxt 3/4

1. Add runtime config:

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apibillSiteId: process.env.APIBILL_SITE_ID || '',
      apibillApiUrl: process.env.APIBILL_API_URL || '',
    },
  },
})

2. Create plugin:

// app/plugins/apibill.ts
import { ApiBillClient } from '@nextive/billing-sdk'

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()

  const billing = new ApiBillClient({
    siteId: config.public.apibillSiteId as string,
    apiUrl: config.public.apibillApiUrl as string,
  })

  return { provide: { apibill: billing } }
})

3. Create restriction middleware:

// app/middleware/billing-restriction.global.ts
import { ApiBillClient } from '@nextive/billing-sdk'

const EXCLUDED_ROUTES = ['/login', '/billing', '/billing/restricted']

export default defineNuxtRouteMiddleware(async (to) => {
  // Skip excluded routes
  if (EXCLUDED_ROUTES.some(r => to.path === r || to.path.startsWith(r + '/'))) return

  // Skip on server side
  if (import.meta.server) return

  const { $apibill } = useNuxtApp()
  if (!$apibill) return

  try {
    const restricted = await ($apibill as ApiBillClient).isRestricted()
    if (restricted) {
      return navigateTo('/billing/restricted')
    }
  } catch {
    // Fail open — don't block on API errors
  }
})

4. Use in components:

<script setup>
const { $apibill } = useNuxtApp()
const summary = await $apibill.getBillingSummary()
</script>

<template>
  <div v-if="summary.billing.unpaidCount > 0" class="alert">
    You have {{ summary.billing.unpaidCount }} unpaid invoice(s).
    Total due: {{ summary.billing.totalDue }} {{ summary.billing.currency }}
  </div>
</template>

5. Create a restricted page:

<!-- app/pages/billing/restricted.vue -->
<template>
  <div class="flex items-center justify-center min-h-screen">
    <div class="text-center max-w-md">
      <h1 class="text-2xl font-bold text-red-600">Access Restricted</h1>
      <p class="mt-2 text-gray-600">
        Your access has been restricted due to overdue invoices.
        Please pay your outstanding invoices to restore access.
      </p>
      <NuxtLink to="/billing" class="mt-4 inline-block px-4 py-2 bg-primary text-white rounded">
        View Invoices
      </NuxtLink>
    </div>
  </div>
</template>

Vue 3 + Vuetify (or any Vue 3 project)

1. Initialize in main.ts:

// main.ts
import { initApiBill } from '@nextive/billing-sdk/vue'

initApiBill({
  siteId: import.meta.env.VITE_APIBILL_SITE_ID,
  apiUrl: import.meta.env.VITE_APIBILL_API_URL,
})

2. Add router guard:

// router/index.ts
import { createBillingGuard } from '@nextive/billing-sdk/vue'

const router = createRouter({ ... })

router.beforeEach(createBillingGuard({
  restrictedRoute: '/billing/restricted',
  excludeRoutes: ['/login', '/billing', '/billing/restricted'],
}))

3. Use in components:

<script setup>
import { useApiBill } from '@nextive/billing-sdk/vue'
import { ref, onMounted } from 'vue'

const billing = useApiBill()
const summary = ref(null)

onMounted(async () => {
  summary.value = await billing.getBillingSummary()
})
</script>

Vanilla JavaScript / Any Framework

import { ApiBillClient } from '@nextive/billing-sdk'

const billing = new ApiBillClient({
  siteId: 'YOUR_SITE_ID',
  apiUrl: 'https://your-api.com/api',
  onRestriction: (summary) => {
    // Show modal, redirect, etc.
    window.location.href = '/billing/restricted'
  },
})

// Check on app load
await billing.checkRestriction()

// Get data
const summary = await billing.getBillingSummary()
const invoices = await billing.getInvoices('unpaid')

Billing Page Example

Create a billing page in your admin panel to show invoices and allow payment:

<script setup>
import { ApiBillClient } from '@nextive/billing-sdk'

const billing = new ApiBillClient({
  siteId: 'YOUR_SITE_ID',
  apiUrl: 'https://your-api.com/api',
})

const summary = ref(null)
const invoices = ref([])
const customInvoices = ref([])
const loading = ref(true)

onMounted(async () => {
  const [s, inv, cinv] = await Promise.all([
    billing.getBillingSummary(),
    billing.getInvoices(),
    billing.getCustomInvoices(),
  ])
  summary.value = s
  invoices.value = inv
  customInvoices.value = cinv
  loading.value = false
})

async function pay(invoiceId, type = 'invoice') {
  const { gatewayUrl } = type === 'invoice'
    ? await billing.payInvoice(invoiceId)
    : await billing.payCustomInvoice(invoiceId)
  window.location.href = gatewayUrl
}
</script>

Environment Variables

| Variable | Description | |---|---| | APIBILL_SITE_ID or VITE_APIBILL_SITE_ID | Your Site ID from ApiBill admin panel | | APIBILL_API_URL or VITE_APIBILL_API_URL | ApiBill API base URL |


How restrictionActive Works

  • If any unpaid invoice with mode restricted has its due date fully passed (after 11:59 PM), restrictionActive becomes true
  • Invoices with mode flexible never trigger restriction
  • If an invoice has an extendedDueDate, that date is used instead of dueDate
  • The SDK caches the billing summary (default 5 min) to avoid excessive API calls

License

MIT

apibill-js-sdk