Core concepts and storage
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.
| Method | Return 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 method | Behavior |
|---|---|
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.