跳到正文
Indiana
控制台
开发文档
章节目录 / 权益、余额与用量

权益、余额与用量

检查权益、上报用量、管理余额与 Entity,并为 AI 调用计费。

API v1更新于

检查权益并上报用量

执行功能前调用 checkEntitlement,完成后调用 trackUsage。数量都是十进制字符串。

usage.tsTypeScript
import { createIndianaServer } from "@tinkerlandai/indiana-sdk/server"; const indiana = createIndianaServer({  baseUrl: process.env.INDIANA_API_URL!,  apiKey: process.env.INDIANA_API_KEY!,  scope: { projectId: process.env.INDIANA_PROJECT_ID!, environment: "sandbox" },});const featureId = process.env.INDIANA_FEATURE_ID!; async function main() {  // 1. Find or create the Customer for your signed-in user.  const { customer } = await indiana.getOrCreateCustomer({ externalUserId: "user-42" });   // 2. Check access before doing the work.  const { check } = await indiana.checkEntitlement({    customerId: customer.id,    requirement: { internal_feature_id: featureId, quantity: "1", properties: {} },  });  if (!check.allowed) return console.log("blocked:", check.reason);   // 3. Report usage after the work succeeds. Use your own event ID in production.  const { receipts } = await indiana.trackUsage({    customerId: customer.id,    command: { internal_feature_id: featureId, quantity: "1", idempotencyKey: crypto.randomUUID() },  });  console.log("recorded:", receipts[0]?.accepted);} main().catch((error) => {  console.error(error);  process.exitCode = 1;});
  • 为每次用量生成并保存 idempotencyKey;结果未知时用同一个 key 重试,不会重复计费。
  • HTTP 200 不代表已扣减:检查每条回执的 accepted 和 reason。

先预留、后确认

耗时任务可以先预留额度,完成后按实际数量确认,失败时释放。

reserve.tsTypeScript
import { createIndianaServer } from "@tinkerlandai/indiana-sdk/server"; const indiana = createIndianaServer({  baseUrl: process.env.INDIANA_API_URL!,  apiKey: process.env.INDIANA_API_KEY!,  scope: { projectId: process.env.INDIANA_PROJECT_ID!, environment: "sandbox" },}); const feature = process.env.INDIANA_FEATURE_ID!; // Hold credits before long-running work; keys are persisted per job.export async function runJob(customerId: string, jobId: string, estimate: string) {  const { receipt } = await indiana.mutateBalance({    customerId,    command: {      operation: "reserve",      internal_feature_id: feature,      quantity: estimate,      properties: {},      idempotencyKey: `${jobId}:reserve`,      expiresInSeconds: 600,    },  });  if (!receipt.accepted) return { started: false as const, reason: receipt.reason };  return { started: true as const, reservationId: receipt.id };} export async function finishJob(customerId: string, jobId: string, reservationId: string, actual: string | null) {  const command = actual    ? { operation: "confirm" as const, operationId: reservationId, quantity: actual, idempotencyKey: `${jobId}:confirm` }    : { operation: "release" as const, operationId: reservationId, idempotencyKey: `${jobId}:release` };  const { receipt } = await indiana.mutateBalance({ customerId, command });  return receipt;}

读取余额与账本

balances.tsTypeScript
import { createIndianaServer } from "@tinkerlandai/indiana-sdk/server"; const indiana = createIndianaServer({  baseUrl: process.env.INDIANA_API_URL!,  apiKey: process.env.INDIANA_API_KEY!,  scope: { projectId: process.env.INDIANA_PROJECT_ID!, environment: "sandbox" },}); export async function readBalances(customerId: string) {  const { holdings } = await indiana.readHoldings({ customerId });  const { ledger } = await indiana.readLedger({    customerId,    query: { type: null, from: null, to: null, after: null, limit: 20 },  });  return { holdings, ledger };}
余额管理
任务方法
补发或扣回额度manageBalanceGrant, listBalanceGrants
修正单个余额adjustBalance, readBalanceSource
直接设定用量setUsage, readUsage
批量上报用量submitUsageBatch, readUsageBatch
对账单与统计readCreditStatement, readUsageAnalytics, readCreditAnalytics
按工作区或设备计量manageUsageEntity
席位分配readSeats, manageSeat

余额管理

  • 补发或扣回额度

    方法
    manageBalanceGrant, listBalanceGrants
  • 修正单个余额

    方法
    adjustBalance, readBalanceSource
  • 直接设定用量

    方法
    setUsage, readUsage
  • 批量上报用量

    方法
    submitUsageBatch, readUsageBatch
  • 对账单与统计

    方法
    readCreditStatement, readUsageAnalytics, readCreditAnalytics
  • 按工作区或设备计量

    方法
    manageUsageEntity
  • 席位分配

    方法
    readSeats, manageSeat

按 AI 调用计费

把中间件传给 AI SDK 的 wrapLanguageModel,每次调用按实际 token 用量计费。

ai-billing.tsTypeScript
import {  createAiUsageMiddleware,  createConfiguredAiPricing,  createIndianaServer,  type AiUsageRecord,} from "@tinkerlandai/indiana-sdk/server"; const indiana = createIndianaServer({  baseUrl: process.env.INDIANA_API_URL!,  apiKey: process.env.INDIANA_API_KEY!,  scope: { projectId: process.env.INDIANA_PROJECT_ID!, environment: "sandbox" },}); // Your own durable store for usage records and frozen quotes.declare function saveUsageRecord(record: AiUsageRecord): Promise<void>; export async function billingMiddleware(customerId: string, callId: string) {  const featureId = process.env.INDIANA_AI_FEATURE_ID!;  const pricing = await createConfiguredAiPricing(indiana, {    internal_feature_id: featureId,    customerId,  });  return createAiUsageMiddleware({    pricing,    client: indiana,    modelId: "openai/gpt-4o",    reasoning: "output",    context: () => ({ customerId, internal_feature_id: featureId, idempotencyKey: callId }),    persist: saveUsageRecord,  });}// Pass the result to wrapLanguageModel({ model, middleware }) from the AI SDK.
  • 每次模型调用使用新的 idempotencyKey,并在 persist 中保存记录,用于失败后恢复。
  • modelId 写成 provider/model;后端需要能访问 https://models.dev 获取模型价格。

相关接口

权益与商品展示 (4)
checkEntitlement, resolveOffering, resolvePaywall, readHoldings
余额、用量与账本 (16)
readBalanceSource, adjustBalance, readUsage, setUsage, manageBalanceGrant, listBalanceGrants, manageUsageEntity, readUsageAnalytics, readCreditAnalytics, submitUsageBatch, readUsageBatch, readLedger, readCreditStatement, quoteBalance, trackUsage, mutateBalance
席位 (2)
readSeats, manageSeat
AI 定价 (1)
readAiPricing

相关:路径、凭据与权限见全部接口