@vellumcharter/sdk
v0.7.1
Published
Thin HTTP client for the VellumCharter entitlements + billing API
Maintainers
Readme
@vellumcharter/sdk
Thin, dependency-free TypeScript client for the VellumCharter entitlements + billing API. Server-side only — it carries a secret API key; never ship it to a browser.
Install
npm install @vellumcharter/sdkRequires Node 18+ (uses the global fetch).
Usage
import { VellumCharterClient } from '@vellumcharter/sdk';
const vellum = new VellumCharterClient({
apiKey: process.env.VELLUM_API_KEY!, // vlm_<tenantId>.<secret>
tenantId: 'sideproj1',
cacheTtlMs: 30_000, // optional (default 30s; 0 disables)
// baseUrl defaults to https://api.vellumcharter.com
});
// Gate a feature:
if (await vellum.can('cust_123', 'exports')) {
// ...allow the export
}
// Or inspect the full set:
const ent = await vellum.getEntitlements('cust_123');
ent.isActive(); // true for active/trialing
ent.has('reports'); // boolean
ent.config<number>('max_users'); // typed config read
ent.found; // false when the customer has no record
// Start a Checkout Session (returns the hosted checkout URL to redirect to):
const { url } = await vellum.createCheckout({
accountId: 'acme',
planId: 'pro',
planVersion: 1,
seats: 3,
successUrl: 'https://app.example.com/billing/ok',
cancelUrl: 'https://app.example.com/billing/cancel',
});
// Drop a cached read once you know it changed:
vellum.invalidate('cust_123');Reads are cached with a short TTL (default 30s), and a customer with no
entitlements returns an empty, no-access set rather than throwing — so can()
and has() are always safe.
Billing facade
Uncached pass-throughs to the billing endpoints (the payment platform still
owns invoicing/proration/dunning). Shapes are typed (SubscriptionView,
PaymentMethod, Invoice) in the server's camelCase / ISO-timestamp form:
const sub = await vellum.getSubscription('acme', 'unit_1'); // SubscriptionView
const methods = await vellum.listPaymentMethods('acme'); // PaymentMethod[]
const invoices = await vellum.listInvoices('acme', 'unit_1'); // Invoice[]
const pdf = await vellum.invoicePdfUrl('acme', 'in_123'); // hosted PDF URL
await vellum.setDefaultPaymentMethod('acme', 'pm_123');
await vellum.setSubscriptionPaymentMethod('acme', 'unit_1', 'pm_123');
await vellum.removePaymentMethod('acme', 'pm_123');
await vellum.cancelSubscription('acme', 'unit_1', /* atPeriodEnd */ true);Provisioning & subscriptions
Register accounts and customers, manage their status, and create subscriptions server-side (no hosted page; the account must have a saved card):
await vellum.createAccount({
accountId: 'acme',
email: '[email protected]',
createBillingCustomer: true,
});
await vellum.createCustomer({ accountId: 'acme', customerId: 'unit_1', email: '[email protected]' });
await vellum.setAccountStatus('acme', 'suspended');
await vellum.setCustomerStatus('acme', 'unit_1', 'disabled');
// Capture a card without charging, then subscribe directly:
const { url } = await vellum.createSetupCheckout({
accountId: 'acme',
successUrl: 'https://app.example.com/billing/ok',
cancelUrl: 'https://app.example.com/billing/cancel',
});
const { subscriptionId } = await vellum.createSubscription({
accountId: 'acme',
customerId: 'unit_1',
planId: 'pro',
planVersion: 1,
seats: 2,
});Credits
Prepaid, pay-as-you-go balances. consumeCredits is idempotent on your key and
all-or-nothing — it throws VellumCharterApiError with status === 409 on an
insufficient balance (nothing is deducted):
const { url } = await vellum.createCreditCheckout({
accountId: 'acme',
customerId: 'unit_1',
creditTypeId: 'render_minutes',
packId: 'pack_1000',
quantity: 2,
successUrl: 'https://app.example.com/credits/ok',
cancelUrl: 'https://app.example.com/credits/cancel',
});
const credits = await vellum.listCredits('unit_1'); // CreditBalance[]
const bal = await vellum.getCreditBalance('unit_1', 'render_minutes'); // CreditBalance
const r = await vellum.consumeCredits('unit_1', {
creditTypeId: 'render_minutes',
amount: 30,
idempotencyKey: 'render:job_42',
});Errors
VellumCharterAuthError on 401/403; VellumCharterApiError (with status and
body) on other non-2xx responses.
API reference
Full endpoint + webhook contract: https://api.vellumcharter.com/openapi.json
