Work in progress. Some documented features are not live yet.

Define your pricing

Set fixed prices, quantity rates, and callback prices in credits.

Define credit types and feature prices in orbyte.config.ts. The property names in features become the keys you use with check and track.

orbyte.config.ts
import { credit, feature, Orbit, usd } from "@orbytelabs/credit";

export const credits = credit("credits", "Credits").worth(usd("0.01"));

export default Orbit({
  features: {
    "api-call": feature("API call", "request", credits(1)),
    inference: feature(
      "AI inference",
      "request",
      usd
        .markup("10%", (data: { costUsd: string }) => data.costUsd)
        .in(credits),
    ),
  },
});

Prices must be nonnegative. A price of zero records usage without deducting credits. Use decimal strings for fractional amounts, such as credits("0.125").

Fixed prices

credits(1) charges one credit per unit. feature("API call", "request", credits(1)) labels that unit as a request. Omitting the unit with feature("API call", credits(1)) uses "use".

The event quantity defaults to 1. To charge for five requests at once:

import { track } from "@orbytelabs/credit";

await track("api-call", "customer_123", {
  id: "batch_123:api-calls",
  quantity: 5,
});

This deducts five credits. The deployed catalog supplies the fixed price. The generated _orbyte.ts types the name without loading your config. You can still pass a feature object from your config.

Prices per quantity

Use .per(amount, quantity) to express a proportional rate. For example, this separate configuration prices 1,000 input units at 10 credits:

orbyte.config.ts
import { credit, feature, Orbit } from "@orbytelabs/credit";

export const credits = credit("credits", "Credits");

export default Orbit({
  features: {
    "input-units": feature("Input units", "unit", credits.per(10, 1_000)),
  },
});

An event with quantity: 250 costs 2.5 credits. This is a proportional rate, so the customer does not pay for a whole block of 1,000.

The API calculates ceil(costNanocredits × quantity / quantityPerUnit). It rounds up once for the event, to the next nanocredit. Splitting one quantity across several events can therefore produce a different total at nanocredit precision.

Quantities must be positive safe integers. For period features, each event must have quantity 1, even when the configured price uses .per(...).

Prices from event data

Use a callback when the amount depends on data available to your server. With the inference feature from the first config on this page:

import { check, track } from "@orbytelabs/credit";
import config from "./orbyte.config";

const data = { costUsd: "0.02" };
const access = await check(config.features.inference, "customer_123", { data });

if (!access.allowed) throw new Error("Not enough credits.");

// Perform the work priced by this data.
await track(config.features.inference, "customer_123", {
  id: "request_123:inference",
  data,
});

A provider cost of $0.02 plus 10% is $0.022. At $0.01 per credit, this event costs 2.2 credits.

Pass the config feature object so the SDK has the callback and its data type. A feature key alone cannot evaluate callback pricing. Callbacks return the total event charge and require quantity 1, which is the default.

The SDK evaluates the callback once before each check or track request, then sends the resolved nanocredit amount. It does not send the callback or raw data to the API. Automatic transport retries reuse that resolved amount.

Keep the callback and its input on your trusted server. Validate customer input before using it to calculate a charge. If the final cost is only known after work finishes, a check using an estimate cannot guarantee that the wallet will cover the final charge.

Markup and percentage

Both helpers require a callback selecting the base amount:

PriceCharge when the base is 10 credits
credits((data: { amount: string }) => data.amount)10 credits
credits.markup("10%", (data: { amount: string }) => data.amount)11 credits, including the base
credits.percent("10%", (data: { amount: string }) => data.amount)1 credit, only the percentage

The same helpers work with usd. A callback can calculate a price from several inputs before returning a decimal amount.

Convert dollar costs to credits

Declare a value with .worth(usd(...)), then convert a USD price with .in(credits):

import { credit, usd } from "@orbytelabs/credit";

const credits = credit("credits", "Credits").worth(usd("0.01"));
const imagePrice = usd("0.04").in(credits); // Four credits.

The conversion uses the declared value in your server code. It does not exchange balances or set a customer purchase price. A plain usd("0.04") price uses a separate USD-denominated balance; .in(credits) makes it spend your credit balance instead.

Only USD prices support .in(...). The destination credit must have a positive fixed USD value.

Precision and limits

One credit equals 1,000,000,000 nanocredits. Fixed credit amounts and top-ups support up to nine decimal places. Callback charges and proportional rates round up once when the final event charge is calculated.

API amounts are integer strings, such as "2500000000" for 2.5 credits. The maximum balance or individual charge is "9223372036854775807" nanocredits. Avoid converting these strings to JavaScript number for arithmetic; use BigInt.

Apply changes

Deploy catalog changes with the SDK CLI. Fixed-price changes affect new events after deployment. An identical retry of an existing event returns its original transaction and original charge.

Callback functions remain in your application code. Deploy the application when changing their calculation, and sync the catalog when changing the feature's credit, pricing mode, labels, or period. Callback features store pricingMode: "callback" and a zero catalog rate because each request supplies its resolved charge.

After a feature's first period charge, its deduplication period is locked. Use a new feature key to change that policy. See usage periods.

On this page