Vatly
JavaScript Fluent

Installation and configuration

Fluent 0.1.0-alpha.2 requires SDK 0.3.0-alpha.4.

Fluent 0.1.0-alpha.2 requires SDK 0.3.0-alpha.4. Pin both during alpha:

npm install --save-exact @getvatly/sdk@0.3.0-alpha.4 @getvatly/fluent@0.1.0-alpha.2

Use Node 20+ or a runtime with Fetch and Web Crypto. ESM, CommonJS, and TypeScript declarations are included. Keep keys and secrets on the server, never in browser code or NEXT_PUBLIC_* variables.

Create the billing service

Pass your server's VATLY_API_KEY to this factory:

import { VatlyClient } from '@getvatly/sdk';
import { Vatly, type Wiring } from '@getvatly/fluent';

export function createBilling(
  apiKey: string,
  drivers: Omit<Wiring, 'api' | 'redirectUrlSuccess' | 'redirectUrlCanceled'> = {},
) {
  return new Vatly({
    ...drivers,
    api: new VatlyClient({ apiKey, timeoutMs: 15_000, maxRetries: 2 }),
    redirectUrlSuccess: 'https://app.example.com/billing/return',
    redirectUrlCanceled: 'https://app.example.com/billing/canceled',
  });
}

test_ keys select test mode; live_ keys charge real money. Both use the same API URL. All IDs and bindings must match the key's storefront and mode.

Checkout creation needs only api and redirect URLs. Add storage drivers for bindings, local subscription updates, and webhook persistence. Missing drivers fail when used. For webhooks, also set webhookSecret from VATLY_WEBHOOK_SECRET, the endpoint's signing secret—not the API key.

Use vatly.api for SDK operations without a Fluent helper, including catalogue management, pagination, and webhook endpoints.

Handle errors and retries

import { VatlyValidationError } from '@getvatly/sdk';
import { FluentError, type Vatly } from '@getvatly/fluent';

export async function renameCustomer(vatly: Vatly, customerId: string, name: string) {
  try {
    return await vatly.customer(customerId).update({ name });
  } catch (error) {
    if (error instanceof VatlyValidationError) {
      return { validationErrors: error.errors };
    }
    if (error instanceof FluentError) throw error; // Fix local input or wiring.
    throw error; // Preserve SDK status, details, and cause for your error handler.
  }
}

SDK errors pass through unchanged. Most local input and wiring errors use FluentError; missing billing-update redirects throw a plain Error in this alpha. Reuse an idempotencyKey when retrying the same mutation: a timeout does not mean it failed. See checkout retries.

For HTTP options and field details, see the API reference and errors guide.

Copyright © 2026