Billwave
SDK Reference

Configuration

SDK initialization and configuration options

Configuration

Configure the Billwave SDK with your API keys and environment settings.

Initialization

import { Billwave } from "@digvijay-x1/billwave";

const billwave = new Billwave({
  // billwave_sk_test_… selects sandbox, billwave_sk_live_… selects live
  secretKey: process.env.BILLWAVE_SECRET_KEY,
});

Configuration Options

OptionTypeRequiredDescription
secretKeystring✅Your API secret key. Scoped keys (billwave_sk_test_… / billwave_sk_live_…) also select the environment
mode"sandbox" | "live"-Environment. Required for legacy (unscoped) keys; must agree with a scoped key
apiUrlstring-Custom API URL for self-hosted deployments (stands in for mode)
debugboolean-Enable debug logging
catalogCatalogEntry[]-Declarative plan/feature definitions

Environments

Billwave has two fully isolated environments, each on its own host:

EnvironmentHostKey prefix
sandboxhttps://sandbox.billwave.examplebillwave_sk_test_
livehttps://api.billwave.examplebillwave_sk_live_

A key only works against its own environment — a sandbox key sent to the live API is rejected with 401 environment_mismatch before anything is written. Every response also echoes where it landed: the X-Billwave-Environment header (sandbox or live) plus X-Billwave-Organization, and check()/track() results include environment in the body.

The SDK never defaults to live

The environment is resolved from, in order:

  1. apiUrl — explicit host (self-hosted / local)
  2. mode — explicit "sandbox" or "live"
  3. the key prefix — billwave_sk_test_… → sandbox, billwave_sk_live_… → live

If none of these determine it (a legacy billwave_sk_… key with no mode), the client still constructs, but the first request throws an BillwaveError with code config_error instead of silently talking to production. If mode contradicts the key's scope, that is also a config_error.

// Scoped key: nothing else needed
const billwave = new Billwave({ secretKey: process.env.BILLWAVE_SECRET_KEY });
billwave.mode; // "sandbox" | "live", inferred from the key
billwave.apiUrl; // "https://sandbox.billwave.example/v1"

// Legacy key: say which environment you mean
const legacy = new Billwave({
  secretKey: process.env.BILLWAVE_SECRET_KEY, // billwave_sk_…
  mode: "sandbox",
});

Use the dashboard to create one key per environment; legacy keys keep working on both hosts but should be rotated.

Custom API URL

For self-hosted deployments or custom endpoints, use apiUrl. This takes precedence over mode:

const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_SECRET_KEY,
  apiUrl: "https://billing.mycompany.com",
  // mode is ignored when apiUrl is provided
});

URL Resolution Priority

The SDK resolves the API URL in this order:

  1. Explicit apiUrl (highest priority)
  2. mode → https://sandbox.billwave.example/v1 or https://api.billwave.example/v1
  3. Key prefix → same hosts, inferred from billwave_sk_test_ / billwave_sk_live_
  4. Otherwise: unresolved — requests throw config_error (there is no default host)

Debug Mode

Enable debug mode for verbose logging:

const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_SECRET_KEY,
  mode: "sandbox",
  debug: true,
});

With Catalog

Pass a declarative catalog for plan/feature management:

import { metered, boolean, plan } from "@digvijay-x1/billwave";

const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_SECRET_KEY,
  mode: "live",
  catalog: [
    plan("pro", {
      name: "Pro",
      price: 2900,
      currency: "USD",
      interval: "monthly",
      features: [
        metered("api-calls").limit(10000),
        boolean("premium-support").enabled(),
      ],
    }),
  ],
});

// Sync catalog to server
await billwave.sync();

Runtime Configuration

Override configuration at runtime (useful for CLI tooling):

const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_SECRET_KEY,
});

// Point at sandbox (both calls re-resolve billwave.mode / billwave.apiUrl)
billwave.setSecretKey(process.env.BILLWAVE_SANDBOX_SECRET_KEY);
billwave.setApiUrl("https://sandbox.billwave.example/v1");

Best Practices

  1. Use environment variables - Never hardcode API keys
  2. One scoped key per environment - billwave_sk_test_… for sandbox, billwave_sk_live_… for live; the API refuses the wrong host
  3. Check the echo - X-Billwave-Environment / result.environment tell you where a request actually landed
  4. Custom URL stands in for mode - With apiUrl, mode is optional but must still agree with a scoped key

Examples

Development Setup

// config.ts
export const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_SANDBOX_SECRET_KEY!,
  mode: "sandbox",
  debug: process.env.NODE_ENV === "development",
});

Production Setup

// config.ts
export const billwave = new Billwave({
  secretKey: process.env.BILLWAVE_LIVE_SECRET_KEY!,
  mode: "live",
});

Dynamic Mode

// config.ts
const mode = process.env.BILLWAVE_MODE as "sandbox" | "live" | undefined;
const secretKey =
  mode === "sandbox"
    ? process.env.BILLWAVE_SANDBOX_SECRET_KEY
    : process.env.BILLWAVE_LIVE_SECRET_KEY;

export const billwave = new Billwave({
  secretKey: secretKey!,
  mode, // undefined is fine with scoped keys; a legacy key needs it set
});

On this page

Ask about billwave

Ready

Start a new chat below.

Powered by Cull