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

@unprice/api

v0.3.1

Published

TypeScript SDK for AI credits and agent usage. Authorize runs, reserve customer credits, and settle usage.

Readme

@unprice/api

TypeScript SDK for the Unprice public API.

Use it from server-side code to check access, consume usage, reserve budgeted runs, inspect wallet credits, and follow usage evidence through the customer money path.

Installation

pnpm add @unprice/api

Example

import { Unprice } from "@unprice/api"

const unprice = new Unprice({
  token: process.env.UNPRICE_TOKEN!,
})

const { result, error } = await unprice.usage.consume({
  customerId: "cus_1234567890",
  featureSlug: "ai-messages",
  eventSlug: "completions",
  idempotencyKey: "req_123",
  properties: {
    aiMessages: 1,
    inputTokens: 1840,
    outputTokens: 620,
  },
})

if (error) {
  throw new Error(error.message)
}

if (!result.allowed) {
  return new Response("Usage limit reached", { status: 429 })
}

Use access.check for read-only shadow checks and usage.record for async usage evidence. For a multi-step workload, call runs.start once, runs.settle after each completed provider step, and runs.end once. runs.consume remains the pre-work enforcing operation.

Reserve cost before expensive work

Use reservations.reserve when one provider call or other expensive operation must not start until the customer can cover a developer-defined maximum cost.

import { generateText } from "ai"
import { Unprice } from "@unprice/api"

const unprice = new Unprice({ token: process.env.UNPRICE_TOKEN! })
const messageId = "message_123"

const { result: reservation, error } = await unprice.reservations.reserve({
  customerId: "cus_1234567890",
  maximumAmountMinor: 10,
  idempotencyKey: messageId,
})

if (error) {
  // Do not call the provider when Unprice cannot reserve the maximum cost.
  return new Response("Budget unavailable", { status: 402 })
}

const generation = await generateText({
  model,
  maxOutputTokens: 2_000,
  prompt,
})

const settlement = await reservation.settle({
  featureSlug: "ai-tokens",
  eventSlug: "ai-completion",
  properties: {
    input_tokens: generation.usage.inputTokens,
    output_tokens: generation.usage.outputTokens,
  },
})

if (
  settlement.error ||
  (!settlement.result.accepted && settlement.result.reason !== "duplicate")
) {
  throw new Error("Usage could not be settled")
}

maximumAmountMinor uses the customer's plan currency in minor units. For a USD plan, 10 is $0.10. Set the provider's output limit when it supports one so the reserved amount can fully fund the provider usage. If actual usage costs more, settlement still records all usage and returns a partially_funded or unfunded funding status. Unprice never increases the reservation or captures more than maximumAmountMinor. For settlement, accepted means that Unprice recorded the usage; the funding fields state how much the reservation covered.

Call reservation.release() only when the operation produced no billable usage. If the provider failed after it did billable work and reports usage, settle that usage instead. Do not release after a settlement error because the provider cost can already exist; retry settlement with the same reservation handle. Settlement records the incurred usage without enforcing the feature limit, captures the safely funded cost from the reserved money envelope, and then closes the run. An unclosed reservation expires one hour after it starts. The Durable Object then releases its unused reserved funds. Pass expiresAt as an epoch-millisecond timestamp when the operation needs a different window. The timestamp cannot be more than 24 hours after the reservation starts.

For streaming APIs, reserve before streamText, settle from onFinish, and apply the same provider-specific decision on errors. The lower-level runs API remains available for workflows that need several usage events or a serializable run identifier.

Monetization configuration

monetization.get and monetization.apply let you describe a project's plans, features, and events as one configuration document instead of clicking through the dashboard. Both require a config API key. The API rejects a runtime key. Keep the key types separate because a config key can rewrite your pricing, the runtime key cannot.

const unprice = new Unprice({ token: process.env.UNPRICE_CONFIG_TOKEN! })

const { result, error } = await unprice.monetization.apply({
  config: {
    plans: [
      {
        slug: "pro",
        title: "Pro",
        version: {
          currency: "USD",
          paymentProvider: "stripe",
          billingConfig: { name: "monthly", interval: "month", intervalCount: 1 },
          features: [{ featureSlug: "tokens", featureType: "flat", config: { price: "10.00" } }],
        },
      },
    ],
  },
})

apply writes draft plan versions and never publishes. A human reviews the drafts and publishes them from the dashboard; result.reviewUrl links to the first draft the call created. Until someone publishes, nothing you sent affects a live customer. There is no publish method in this SDK, by design.

result.plans reports one outcome per plan in the order you sent them, and result.staleDrafts reports drafts left behind by earlier documents.

Call monetization.get to read the current configuration back in the shape apply accepts. It takes no arguments because the project comes from the key. Alongside the document, it returns unrepresentablePlans for plans the document cannot describe and warnings for stored configuration the document omits. The call reports these omissions instead of discarding them.

License

MIT. All project-owned packages under packages/** are licensed separately from the AGPL-3.0-only Unprice core. You can embed this package in an application without applying the core license to the application.