# TypeScript SDK

Source: https://docs.orbytelabs.com/sdk

Check balances, track usage, and fund wallets from your server.

`@orbytelabs/credit` provides the Credit SDK and the `orbyte` catalog CLI. It requires Node.js 24+ and ESM.

```sh
pnpm add @orbytelabs/credit
```

Follow the [quickstart](/quickstart) to create a key and deploy your first catalog.

Keep the SDK on your server. Set `ORBYTE_API_KEY` in your environment. The SDK uses `https://api.orbytelabs.com` automatically; you do not need to set an API URL. See [authentication](/authentication) for keys and permissions.

## Use the direct functions [#use-the-direct-functions]

Use `check`, `track`, `topup`, and `getWallet` for day-to-day billing.

```ts
import { check, credit, getWallet, topup, track } from "@orbytelabs/credit";

const identity = "customer_123";
const credits = credit("credits");

// Run once for a confirmed purchase or grant.
await topup(identity, credits(100), {
  idempotencyKey: "purchase_123",
});

const access = await check("api-call", identity, { quantity: 2 });
if (!access.allowed) throw new Error("Usage is not allowed.");

// Perform the work, then record its completed usage.
await track("api-call", identity, {
  id: "request_batch_123",
  quantity: 2,
});

const wallet = await getWallet(identity);
console.log(wallet?.balances);
```

This example uses the `credits` credit type and `api-call` feature from the quickstart. Choose IDs from your own purchase and usage records. Keep the same ID when retrying the same operation.

| Function                           | Result                                                                                                             |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `check(feature, wallet, options?)` | Access result with `allowed`, the required amount, and the current balance. It does not charge or reserve credits. |
| `track(feature, wallet, options?)` | Transaction result with `status`, `transactionId`, and `amountNanocredits`.                                        |
| `topup(wallet, amount, options?)`  | `{ deposit, duplicate }`. The amount must be a fixed, positive credit amount.                                      |
| `getWallet(identity, options?)`    | Wallet with balances, or `null` if it does not exist. It does not create a wallet.                                 |

The `wallet` argument accepts an identity string or an object containing `identity`, including a wallet returned by `getWallet`. Amounts in responses are integer nanocredit strings. One credit equals `1_000_000_000` nanocredits.

When a [plan allowance](/subscriptions) applies, `check` can also return `limit` with `limit`, `used`, `remaining`, `periodStart`, `periodEnd`, and `overage`. The optional `reason` describes a denial, such as `feature_limit_exceeded` or `subscription_inactive`. Always branch on `allowed`; a denied check does not necessarily mean the wallet needs a top-up.

### Check and track options [#check-and-track-options]

| Option     | Applies to          | Meaning                                                                                                          |
| ---------- | ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `quantity` | Both                | Positive integer usage quantity. Defaults to `1`. Accepts a number or bigint up to `Number.MAX_SAFE_INTEGER`.    |
| `entityId` | Both                | Entity to count once within a configured [usage period](/usage-periods).                                         |
| `id`       | `track`             | Unique event ID. The SDK generates a UUID if omitted. Supply your own to retry across calls or process restarts. |
| `data`     | Config feature only | Typed input to a callback price. Pass the actual feature object from your config.                                |

For a fixed price, pass its typed name directly, such as `check("api-call", identity)`. The generated `_orbyte.ts` registers the valid names with the SDK. No runtime import of the config or generated enums is required. Generated `Features` enum values and feature objects from your config remain supported.

Callback prices require the feature object so the SDK can evaluate your function on your server. Generated types reject callback names in string-based calls. See [pricing](/pricing).

`topup` accepts an `idempotencyKey`; it generates a UUID when omitted. See [wallets and top-ups](/wallets-and-topups) for funding after payments and handling duplicate requests.

## Subscriptions and payments [#subscriptions-and-payments]

These functions are also exported from `@orbytelabs/credit`. See [subscriptions and payments](/subscriptions) for Stripe setup, required options, and complete examples.

| Function                                                 | Result                                                                                                                    |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `createCheckout(wallet, plan, options)`                  | `{ id, url }` for a hosted subscription checkout.                                                                         |
| `createTopupCheckout(wallet, amount, options)`           | `{ id, url }` for a paid credit top-up. Credits arrive after payment confirmation.                                        |
| `createBillingPortal(wallet, { returnUrl, ...options })` | `{ url }` for the customer's Stripe billing portal.                                                                       |
| `getSubscription(wallet, options?)`                      | Current subscription, or `null`.                                                                                          |
| `changeSubscription(wallet, plan, options?)`             | Updated subscription after switching plans with immediate prorations.                                                     |
| `cancelSubscription(wallet, options?)`                   | Updated subscription. Defaults to cancellation at period end; `cancelAtPeriodEnd: false` undoes a scheduled cancellation. |

## Connection options [#connection-options]

All functions above accept these options in their final argument. Explicit values override the environment.

| Option   | Default                      |
| -------- | ---------------------------- |
| `apiKey` | `ORBYTE_API_KEY`             |
| `url`    | `https://api.orbytelabs.com` |
| `fetch`  | `globalThis.fetch`           |

The defaults work for both Development and Production; your API key selects the application. For a custom API server, the optional `url` option or `ORBYTE_API_URL` environment variable can override the address. Use an origin with no API path, credentials, query, or fragment. HTTPS is required except for loopback development addresses. A custom `fetch` implementation receives your key and request data.

```ts
import { check } from "@orbytelabs/credit";

const access = await check("api-call", "customer_123", {
  apiKey: process.env.ORBYTE_API_KEY,
});
console.log(access.allowed);
```

The direct functions read the process environment. They do not load `.env.local` themselves; your server or process launcher must load it. The CLI loads `.env.local` next to the config file.

## Use a client for administration [#use-a-client-for-administration]

Create an `OrbyteClient` when you need catalog administration, deposit history, or wallet billing periods. It accepts the same connection options.

```ts
import { OrbyteClient } from "@orbytelabs/credit";

const client = new OrbyteClient();
const application = await client.application();
const features = await client.listFeatures();
const deposits = await client.listDeposits({ identity: "customer_123" });

console.log(application.name, features.length, deposits.length);
```

| Method                                              | Purpose                                                                   |
| --------------------------------------------------- | ------------------------------------------------------------------------- |
| `application()`                                     | Read the key's organization, application, environment, and permissions.   |
| `listCredits()`, `listFeatures()`                   | Read the deployed catalog.                                                |
| `createCredit(input)`, `updateCredit(key, input)`   | Create or update a credit definition.                                     |
| `createFeature(input)`, `updateFeature(key, input)` | Create or update a feature's price and usage rules.                       |
| `listPlans()`, `getPlan(key)`                       | Read deployed plans and their synchronization status.                     |
| `createPlan(input)`, `updatePlan(key, input)`       | Create or revise a plan's price and feature allowances.                   |
| `getWallet(identity)`                               | Read a wallet or return `null`.                                           |
| `setBillingPeriod(identity, { interval, anchor })`  | Set the wallet period used by features with billing-period deduplication. |
| `createDeposit(input)`                              | Fund a wallet with an explicit nanocredit amount and idempotency key.     |
| `listDeposits({ identity, creditKey? })`            | Read a wallet's deposit history.                                          |
| `check(input)`                                      | Check usage with `{ feature, identity, quantity?, entityId? }`.           |
| `ingest(input)`                                     | Track usage with the same fields plus a required `id`.                    |

List methods collect all pages into an array. See the [API reference](/api) for request fields and permission requirements.

Pass `{ config }` to the constructor to use callback prices through `client.check` and `client.ingest`. The client then requires features from that config and infers their `data` types.

Plan reads require `plans:read`; plan creation and updates require `plans:write`. `PlanInput` and `PlanRecord` describe the request and response. A plan includes `amountCents`, `currency`, a monthly or yearly `interval`, and `featureLimits`. Optional `creditGrants` deposits credits after confirmed creation, renewal, or full-period migration invoices, `topupsEnabled` controls paid top-up checkout, and `featureMultipliers` applies per-plan rates in basis points. Use the same raw `{ creditKey, amountNanocredits }` grant entries as the REST API. See [plans and allowances](/subscriptions) for configuration, included quantities, and overage behavior.

## Deploy your catalog [#deploy-your-catalog]

Use the [`orbyte` CLI](/cli) to deploy credits, features, and plans from `orbyte.config.ts`.

```sh
pnpm exec orbyte deploy --dry-run
pnpm exec orbyte deploy
```

The CLI generates `_orbyte.ts` to type feature names in SDK calls. See [deployment](/cli/deploy) for catalog updates and Production deployment, [watch mode](/cli/dev) for local development, and [generated types](/cli/generated-types) for TypeScript setup.

## Handle failures [#handle-failures]

HTTP errors throw `OrbyteApiError` with `status`, `code`, and `message`. Network failures and interrupted response reads throw `OrbyteTransportError`. Invalid configuration and response data can fail local validation.

Requests time out after 20 seconds per attempt. The SDK makes up to two retries for supported transient failures. It retries reads, updates, checks, event ingestion, and deposits; catalog creation is not retried after an ambiguous transport failure. A recognized `rate_limited` response can be retried for any request.

Automatic event and deposit retries retain the same IDs. If your application starts a fresh SDK call after a failure, pass the original event ID or deposit idempotency key again. See [checking and tracking](/checking-and-tracking) and [errors](/errors).