hasapla

中文文档
0.1.9发布于 2026/11/04Apache-2.0TypeScriptESM + CJS零依赖

TypeScript SDK for Hasapla, the billing platform for AI companies

原始使用文档
文档目录8 节
  1. Installation
  2. Initialization
  3. Balance
  4. Customers
  5. Subscriptions
  6. Usage events
  7. Errors
  8. License

Hasapla Node.js SDK

The official TypeScript SDK for Hasapla, the billing platform for AI companies.

Typed access to customer balances, customers, organizations, features, plans, subscriptions, and usage events for Node.js 18 and newer.

Installation

npm install hasapla

Initialization

Create one client and reuse it throughout your server application. Keep the API key on the server.

import { Hasapla } from "hasapla";

const hasapla = new Hasapla({
    apiKey: process.env.HASAPLA_API_KEY!,
});

Balance

const balance = await hasapla.balance.get({
    extCustomerId: "customer-123",
});
// { balance: 3000, unlimited: false }

Supply exactly one of extCustomerId or extOrganizationId. The SDK maps these to the API's ext_customer_id and ext_organization_id query parameters. Unlimited subscriptions return { balance: null, unlimited: true }; pending limited subscriptions return zero. This endpoint does not authorize usage or refresh expired periods.

This replaces the previous placeholder: the result is now an object rather than a number, and unlimited balances are null instead of -1.

Customers

await hasapla.customers.create({
    email: "[email protected]",
    name: "Example Customer",
    extCustomerId: "customer-123",
});

Subscriptions

Subscribe a customer or organization to a plan. Supply exactly one of customer_uuid or organization_uuid and an interval of "month" or "year".

const subscription = await hasapla.subscriptions.subscribe({
    customer_uuid: "customer-uuid",
    plan_uuid: "plan-uuid",
    interval: "month",
});

Free plans activate immediately. Paid plans remain pending with null period dates and no credit grant. The interval does not select a different catalog price. Subscription fields use the API's snake_case names.

Check a customer's current subscriptions:

const subscriptions = await hasapla.subscriptions.list({
    customer_uuid: "customer-uuid",
    current: true,
});

Use organization_uuid for an organization. The result is an array, which may be empty. Omit current to include historical subscriptions. Pagination accepts limit (1–1000, default 100) and offset (default 0).

Retrieve a subscription by UUID:

const subscription = await hasapla.subscriptions.get("subscription-uuid");

Change the plan or interval immediately:

const replacement = await hasapla.subscriptions.change("subscription-uuid", {
    plan_uuid: "target-plan-uuid",
    interval: "month",
    activate_immediately: true,
    payment_reference_id: "verified-payment-reference",
    amount: 3000,
    currency: "USD",
});

For paid targets, verify payment on your server first and supply the full target price and currency. For free targets, omit all three payment fields. Same-interval changes preserve the renewal date except when moving from free to paid; interval changes start a fresh period. Matching retries return the existing successor, and selecting the same plan and interval makes no changes. Scheduled changes (activate_immediately: false) currently return HTTP 409.

Usage events

await hasapla.events.create({
    extCustomerId: "customer-123",
    featureKey: "api_call",
});

Reserve an event before performing work, then capture it on success or release it otherwise:

const reservation = await hasapla.events.reserve({
    extCustomerId: "customer-123",
    featureKey: "api_call",
});

if (!reservation.key) {
    throw new Error("Reservation key is missing");
}

try {
    await performWork();
    await hasapla.events.capture({ key: reservation.key });
} catch (error) {
    await hasapla.events.release({ key: reservation.key });
    throw error;
}

When the customer has exhausted the feature allowance, reserve throws a 409 error that can be checked with isFeatureLimitReachedError:

import { isFeatureLimitReachedError } from "hasapla";

try {
    await hasapla.events.reserve({
        extCustomerId: "customer-123",
        featureKey: "api_call",
    });
} catch (error) {
    if (isFeatureLimitReachedError(error)) {
        console.error("Feature limit reached");
    } else {
        throw error;
    }
}

Errors

Failed API responses throw HasaplaError with the HTTP status and parsed response body.

import { HasaplaError } from "hasapla";

try {
    await hasapla.customers.get({ externalId: "missing-customer" });
} catch (error) {
    if (error instanceof HasaplaError) {
        console.error(error.status, error.body);
    }

    throw error;
}

License

Apache-2.0

版本与发布记录

hasapla 共发布 10 个版本,首次发布于 2026/08/24;过去 12 个月发布了 10 个版本。

版本发布日期距今
0.1.9latest2026/11/04今天
0.1.82026/11/021 天前
0.1.72026/11/021 天前
0.1.62026/11/013 天前
0.1.52026/09/261 个月前
0.1.42026/09/051 个月前

关于 hasapla 的常见问题

hasapla 是什么?

Hasapla的TypeScript SDK, AI公司的计费平台

如何安装 hasapla?

在项目目录运行 npm install hasapla,或使用 pnpm add / yarn add / bun add。

hasapla 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

hasapla 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

hasapla 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

hasapla 可以商用吗?

hasapla 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

hasapla 还在维护吗?

最新版本 0.1.9 发布于 2026/11/04(今天);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/08/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。