Vatly
JavaScript Fluent

Core concepts and storage

Connect Fluent to your existing tables through storage drivers.

Connect Fluent to your existing tables through storage drivers. Your application owns the database, authentication, and jobs; Fluent supplies the contracts.

import type { Order } from '@getvatly/sdk';
import type { LocalSubscription, Repository, Stored, Wiring } from '@getvatly/fluent';

export function storageDrivers(
  subscriptions: Repository<LocalSubscription>,
  orders: Repository<Stored<Order>>,
): Pick<Wiring, 'subscriptions' | 'orders'> {
  return { subscriptions, orders };
}

Repository behavior

Stored<T> adds hostCustomerId to the SDK resource. It is null for an unattributed customer. LocalSubscription also adds endsAt.

MethodReturn value
findByVatlyId(id)Record or null.
store(data)Saved record, or null to decline storage and skip the local-created event.
update(id, partial)Updated record. Omitted/undefined fields stay unchanged; null clears a nullable field.

Enforce unique Vatly IDs per tenant, storefront, and mode. Adapt existing tables rather than duplicating them. store can match a pending host record using checkout metadata and attach its Vatly ID. Metadata helps match records; it does not authorize access.

refunds and chargebacks use ReversalRepository, which adds listForOrder(id) and listForCustomer(id). Contracts accept sync or async implementations, except webhookCalls.process, which returns a promise.

Billables and bindings

Keep your user, team, or organization as the billable; there is no Billable mixin. CustomerProfile carries vatlyId, email, and optional name. Your application's ID (hostId) is separate from Vatly's customer ID (vatlyId). Authorize both.

CustomerBindings methodBehavior
bind(vatlyId, hostId)Associate IDs atomically; enforce uniqueness on both sides.
record(vatlyId)Record an unattributed customer without clearing an existing binding.
vatlyCustomerIdFor(hostId)Return the Vatly ID or null.
hostCustomerIdFor(vatlyId)Return the host ID or null.

Do not silently reassign bindings. Keep test and live data separate. See customers for creation and lookup examples.

Webhook storage

Wire webhookCalls for deduplication and audit retention, and events for outbox writes. They must share a transaction with repositories and bindings. Use your database's transaction context or request-scoped drivers, not a global variable shared by concurrent requests. The webhook transaction steps define what must commit or roll back together.

For remote resource fields, use the API reference.

Copyright © 2026