Skip to content

TypeScript SDK

Install and use the official PacSpace SDK for TypeScript and Node.js.

The TypeScript SDK wraps the Balance API in a typed Node.js client.

Use it to record usage, derive balances, compare views, create checkpoints, fetch receipts, and verify webhook signatures.

Install

bash
npm install @pacspace-io/sdk

Requires Node.js 18 or later.

Create A Client

typescript
import { PacSpace } from '@pacspace-io/sdk';

const pac = new PacSpace({
  apiKey: process.env.PACSPACE_API_KEY!,
  productionUrl: 'https://app.pacspace.io',
});

Use a pk_live_* key for Production. Use a pk_test_* key for Sandbox and pass the Sandbox URL from your PacSpace dashboard.

Record Usage

typescript
const delta = await pac.balance.emit('cust_acme', -42.5, 'compute_minutes', {
  referenceId: 'usage_2026_05_001',
  metadata: {
    product: 'inference',
    units: 50,
  },
});

console.log(delta.recordId);
console.log(delta.receiptId);
console.log(delta.status);

emit() returns immediately. Store recordId for status checks and receiptId for proof lookup.

To wait for a terminal result:

typescript
const verified = await pac.balance.emitAndWait(
  'cust_acme',
  -42.5,
  'compute_minutes',
  {
    timeout: 30_000,
    pollInterval: 1_000,
  },
);

console.log(verified.status);

Derive A Balance

typescript
const balance = await pac.balance.derive('cust_acme', {
  period: '2026-05',
});

console.log(balance.computedBalance);
console.log(balance.deltaCount ?? balance.deltasCount);

You can also use helpers for common windows:

typescript
await pac.balance.deriveCurrentMonth('cust_acme');
await pac.balance.deriveForPeriod('cust_acme', '2026-05');
await pac.balance.deriveMonthsBack('cust_acme', 3);
await pac.balance.deriveDaysBack('cust_acme', 30);

Compare Two Views

typescript
const report = await pac.balance.compare(
  'cust_acme',
  {
    yours: 95000,
    theirs: 98000,
  },
  {
    period: '2026-05',
  },
);

console.log(report.neutralBalance);
console.log(report.matchesYours);
console.log(report.matchesTheirs);

Compare tells you whether either submitted view matches the balance PacSpace derives from verified deltas.

Checkpoint A Period

typescript
const checkpoint = await pac.balance.checkpoint('cust_acme', {
  period: '2026-05',
});

console.log(checkpoint.proofRoot);
console.log(checkpoint.deltaCount);
console.log(checkpoint.status);

A checkpoint gives the period a single proof root that can be included with an invoice or close package.

Receipts

For customer-scoped receipt data:

typescript
const receipt = await pac.balance.receipt('cust_acme', {
  period: '2026-05',
});

console.log(receipt.proofRoot);
console.log(receipt.verifyUrl);
console.log(receipt.verificationApiUrl);
console.log(receipt.verificationExplorerUrl);

verificationExplorerUrl remains a public response field. Keep it if your integration already stores it.

For receipt-document helpers by receipt ID:

typescript
const result = await pac.balance.receipts.list('cust_acme', { limit: 10 });
const doc = await pac.balance.receipts.get(result[0].receiptId);

const receiptId = pac.balance.receipts.fromUrl(doc.links.permalink);
const emailBody = pac.balance.receipts.emailBody(doc);
const pdfBytes = await pac.balance.receipts.downloadPdf(receiptId);

console.log(emailBody);
console.log(pdfBytes.byteLength);

Customer Records

Every new customerId passed to emit() creates a customer record.

typescript
const { customers } = await pac.balance.customers({
  search: 'cust_',
  limit: 25,
});

const customer = await pac.balance.customer('cust_acme', {
  period: '2026-05',
});

console.log(customers.length);
console.log(customer.computedBalance);

Dashboard customer helpers are also available on pac.customers. They use Dashboard API credentials, not Balance API keys.

Client-Side Submission Helpers

The SDK includes optional client-side helpers for integrations that summarize usage before sending it.

typescript
pac.balance.queueSummary({
  customerId: 'cust_acme',
  delta: -100,
  reason: 'daily_usage',
  referenceId: 'usage_day_2026_05_27',
});

const result = await pac.balance.flushSummaries();

console.log(result.accepted);
console.log(result.failed);

These helpers run in your application process. They are not required for normal emit() usage.

Webhook Verification

typescript
const pac = new PacSpace({
  apiKey: process.env.PACSPACE_API_KEY!,
  productionUrl: 'https://app.pacspace.io',
  webhookSecret: process.env.PACSPACE_WEBHOOK_SECRET,
});

const event = pac.webhooks!.verify(
  req.headers['x-pacspace-signature'] as string,
  req.headers['x-pacspace-timestamp'] as string,
  rawBody,
);

if (event.event === 'delta.verified') {
  console.log(event.data.receiptId);
}

SDK helper types may lag newly launched event names. Signature verification works for any valid PacSpace webhook envelope.

Errors

All SDK errors extend PacSpaceError.

typescript
import {
  PacSpaceError,
  RateLimitError,
  ValidationError,
} from '@pacspace-io/sdk';

try {
  await pac.balance.emit('cust_acme', -100, 'usage');
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(`Retry after ${err.retryAfter} seconds`);
  } else if (err instanceof ValidationError) {
    console.log(err.message);
  } else if (err instanceof PacSpaceError) {
    console.log(err.code);
  }
}

Package Details

DetailValue
npm package@pacspace-io/sdk
Current docs target0.7.0
RuntimeNode.js 18+
LicenseMIT

Next Steps