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

@headlessly/billing

v0.1.1

Published

headless.ly Billing entities — Customer, Product, Price, Subscription, Invoice, Payment

Readme

@headlessly/billing

Stripe is the payment rail. This is the billing system your agent operates.

import { Subscription, Invoice } from '@headlessly/billing'

await Subscription.create({ customer: 'customer_fX9bL5nRd', plan: 'plan_k7TmPvQx' })
await Subscription.upgrade('subscription_mN8pZwKj')

// A subscription cancels — CRM, support, and analytics react instantly
Subscription.cancelled(async (sub, $) => {
  await $.Contact.update(sub.customer, { stage: 'Churned' })
  await $.Ticket.create({ subject: 'Cancellation follow-up', requester: sub.customer })
  await $.Event.create({ type: 'churn', value: sub.plan })
})

Stripe handles payments. headless.ly gives your agent the full billing lifecycle — subscriptions, invoices, plans, upgrades, downgrades — as typed entities in the same graph as your CRM, support, and analytics.

The Problem

You integrated Stripe. Congratulations — you can charge credit cards.

Now build the rest: subscription lifecycle management, plan-based access control, invoice generation, payment failure handling, MRR calculation, churn tracking, upgrade/downgrade logic.

Wire it to your CRM so sales knows when a deal converts to a paying customer. Wire it to support so tickets appear when payments fail. Wire it to analytics so you can track conversion funnels.

That's not a Stripe problem. That's an integration problem. Your billing data lives in Stripe, your CRM data lives in HubSpot, your support data lives in Zendesk, and none of them share a graph.

One Typed Graph

When a subscription cancels in headless.ly, your CRM already knows. Your support system already knows. Your analytics already know. Because they're the same system:

import { Subscription, Invoice } from '@headlessly/billing'

Subscription.cancelled(async (sub, $) => {
  await $.Contact.update(sub.customer, { stage: 'Churned' })
  await $.Ticket.create({ subject: 'Win-back opportunity', requester: sub.customer, priority: 'High' })
  await $.Event.create({ type: 'churn', value: sub.plan })
})

Invoice.voided(async (invoice, $) => {
  await $.Activity.create({
    subject: `Payment failed: ${invoice.number}`,
    type: 'Task',
    priority: 'Urgent',
  })
})

No webhook relay. No Zapier. No data mapping. One graph.

Install

npm install @headlessly/billing

Entities

Customer

Billable customers backed by Stripe — linked to your CRM organizations.

import { Customer } from '@headlessly/billing'

await Customer.create({ name: 'Acme Corp', email: '[email protected]', currency: 'usd' })

Key fields: name, email, stripeCustomerId, paymentMethod, currency, taxExempt

Relationships: → Organization, ← Subscriptions[], ← Invoices[], ← Payments[]

Product

Software products, services, addons, and bundles.

import { Product } from '@headlessly/billing'

await Product.create({
  name: 'Headlessly Pro',
  type: 'Software',
  status: 'Active',
  visibility: 'Public',
})

Key fields: name, tagline, type (Software | Service | Addon | Bundle), status (Draft | Active | Archived), visibility (Public | Private | Hidden), features, stripeProductId

Plan

Pricing plans with trial support and feature limits.

import { Plan } from '@headlessly/billing'

await Plan.create({
  name: 'Pro Monthly',
  product: 'product_e5JhLzXc',
  trialDays: 14,
  status: 'Active',
})

Key fields: name, trialDays, features, limits, status (Draft | Active | Grandfathered | Archived), isFree, isEnterprise

Relationships: → Product, ← Prices[]

Price

Individual price points — monthly, yearly, or one-time.

import { Price } from '@headlessly/billing'

await Price.create({ amount: 4900, currency: 'usd', interval: 'Monthly', plan: 'plan_k7TmPvQx' })

Key fields: amount, currency, interval (Monthly | Quarterly | Yearly | OneTime), active, stripeId

Subscription

The full lifecycle — create, pause, cancel, reactivate, upgrade, downgrade.

import { Subscription } from '@headlessly/billing'

await Subscription.create({ customer: 'customer_fX9bL5nRd', plan: 'plan_k7TmPvQx' })

await Subscription.pause('subscription_mN8pZwKj')
await Subscription.cancel('subscription_mN8pZwKj')
await Subscription.reactivate('subscription_mN8pZwKj')
await Subscription.upgrade('subscription_mN8pZwKj')
await Subscription.downgrade('subscription_mN8pZwKj')

Verbs: pause() · cancel() · reactivate() · upgrade() · downgrade() — each with full lifecycle conjugation

Key fields: status (Active | PastDue | Cancelled | Trialing | Paused | Incomplete), currentPeriodStart, currentPeriodEnd, cancelAtPeriodEnd, trialStart, trialEnd, cancelReason

Relationships: → Customer, → Plan, → Organization

Invoice

Invoices with line items, payment tracking, and Stripe sync.

import { Invoice } from '@headlessly/billing'

await Invoice.create({
  number: 'INV-2026-001',
  customer: 'customer_fX9bL5nRd',
  total: 4900,
  amountDue: 4900,
})

await Invoice.pay('invoice_z3RnWqYp')
await Invoice.void('invoice_z3RnWqYp')

Verbs: pay() · void() — each with full lifecycle conjugation

Key fields: number, subtotal, tax, total, amountDue, status (Draft | Open | Paid | Void | Uncollectible), lineItems, stripeInvoiceId

Payment

Individual payment transactions.

import { Payment } from '@headlessly/billing'

await Payment.create({ amount: 4900, currency: 'usd', customer: 'customer_fX9bL5nRd' })
await Payment.refund('payment_pQ4xLmRn')

Verbs: refund() — with full lifecycle conjugation

Key fields: amount, currency, status (Pending | Succeeded | Failed | Refunded), stripePaymentId

Agent-Native

Your agent connects to one MCP endpoint. It can manage your entire billing stack:

{ "type": "Subscription", "filter": { "status": "Active" } }
{ "type": "Customer", "id": "customer_fX9bL5nRd", "include": ["subscriptions", "invoices"] }
const pastDue = await $.Subscription.find({ status: 'PastDue' })
for (const sub of pastDue) {
  await $.Ticket.create({
    subject: `Payment issue: ${sub.$id}`,
    requester: sub.customer,
    priority: 'Urgent',
  })
}

Cross-Domain Operations

Query results are standard arrays — chain operations with familiar JavaScript:

const customers = await Customer.find({ currency: 'usd' })
for (const customer of customers) {
  const subs = await Subscription.find({ customer: customer.$id, status: 'Active' })
  for (const sub of subs) {
    await Invoice.create({ customer: customer.$id, subscription: sub.$id })
  }
}

License

MIT