Subscriptions
Change an existing subscription with vatly.subscription(localRecord). Load and
authorize the record from your repository; wire that repository
into Vatly so swap, resume, and sync can save changes.
Change plan or quantity
import type { LocalSubscription, Vatly } from '@getvatly/fluent';
export async function schedulePlan(vatly: Vatly, local: LocalSubscription, planId: string) {
return vatly.subscription(local).swap(planId, { quantity: 2 });
}
export async function changeAndInvoice(vatly: Vatly, local: LocalSubscription, planId: string) {
return vatly.subscription(local).swapAndInvoice(planId, { quantity: 2 });
}
export async function changeWithoutCharge(vatly: Vatly, local: LocalSubscription, planId: string) {
return vatly.subscription(local).swapWithoutCharge(planId);
}
Choose one action:
| Method | Options sent to the API |
|---|---|
swap(planId, body?, requestOptions?) | Your update options; without applyImmediately, changes are scheduled. |
swapAndInvoice(...) | Forces applyImmediately: true, invoiceImmediately: true. |
swapWithoutCharge(...) | Forces applyImmediately: true, prorationCharge: false. |
Local plan and quantity follow the API response. A scheduled swap leaves the
current plan unchanged. scheduledUpdate() fetches the pending change;
hasScheduledUpdate() checks whether one exists. See the API reference below
for proration rules.
Cancel and resume
import type { LocalSubscription, Vatly } from '@getvatly/fluent';
export async function cancelNow(vatly: Vatly, local: LocalSubscription, operationId: string) {
await vatly.subscription(local).cancel({
immediately: true,
idempotencyKey: `cancel:${operationId}`,
});
}
export async function resume(vatly: Vatly, local: LocalSubscription) {
const handle = await vatly.subscription(local).resume();
return handle.model();
}
cancel() uses the API's default timing; { immediately: true } cancels now.
Cancellation waits for webhooks to set local endsAt. Resume clears
it after the API succeeds. cancellationReason() fetches the remote reason.
model() returns the local record. sync() fetches and saves the API resource.
state() derives active, valid, recurring, cancelled, onGracePeriod, and
ended from endsAt. Check Vatly's status separately for states such as paused.
Grace-period limitation in this alpha
This alpha's sync() and cancellation reactions set endsAt to
endedAt ?? canceledAt. During a grace period, endedAt can be null and
canceledAt is the cancellation request time, not the access deadline. The local
flags can therefore report an ended subscription while access is still owed.
Keep entitlement decisions separate from state() until this is corrected;
confirm the grace deadline before changing access. Do not use canceledAt as an expiry.
Update billing details
import type { LocalSubscription, Vatly } from '@getvatly/fluent';
export async function billingUpdateUrl(vatly: Vatly, local: LocalSubscription) {
return vatly.subscription(local).updateBilling({
redirectUrlSuccess: 'https://app.example.com/billing/updated',
redirectUrlCanceled: 'https://app.example.com/billing/canceled',
});
}
Redirect to the returned URL; do not log or persist it. This hosted flow updates
billing details, rather than writing address fields directly. Both redirects are
required here or in configuration. Process
subscription.billing_updated to update local payment details.
For all options, eligibility, and fields, see the Subscriptions API reference.