Easy Labs
SDKsNode.jsResources

Subscriptions

Subscriptions — methods, parameters, and examples for @easylabs/node.

A subscription is a recurring billing relationship between a customer and one or more prices. The SDK exposes the full lifecycle — create, update items, pause/resume, apply discounts, report metered usage, preview proration, cancel — plus one-time charges that ride along on the next invoice.

Methods

Lifecycle

easy.createSubscription(body);                       // POST /subscriptions
easy.getSubscription(id);                            // GET /subscriptions/:id
easy.getSubscriptions(params?);                      // GET /subscriptions
easy.updateSubscription(id, body);                   // PATCH /subscriptions/:id
easy.cancelSubscription(id, { at_period_end? });     // DELETE /subscriptions/:id
easy.pauseSubscription(id, { behavior, resumes_at? }); // POST /subscriptions/:id/pause
easy.resumeSubscription(id);                         // POST /subscriptions/:id/resume
easy.getSubscriptionProrationPreview(id, params?);   // GET /subscriptions/:id/proration-preview
const { data: sub } = await easy.createSubscription({
  identity_id: customer.id,
  items: [{ price_id: "PR_monthly", quantity: 1 }],
  instrument_id: paymentInstrumentId,
  proration_behavior: "create_prorations",
  trial_period_days: 14,
  metadata: { plan: "pro_monthly" },
});

// Schedule cancellation at period end:
await easy.cancelSubscription(sub.id, { at_period_end: true });

// Pause until a date:
await easy.pauseSubscription(sub.id, {
  behavior: "mark_uncollectible",
  resumes_at: "2026-08-01T00:00:00Z",
});

await easy.resumeSubscription(sub.id);

pauseSubscription's behavior is "void" | "keep_as_draft" | "mark_uncollectible" — controls how invoices generated during the pause are handled.

Items

easy.addSubscriptionItem(subId, { price_id, quantity? });
easy.updateSubscriptionItem(subId, itemId, { quantity });
easy.removeSubscriptionItem(subId, itemId);

Discounts

easy.applySubscriptionDiscount(subId, body);      // POST /subscriptions/:id/discounts
easy.listSubscriptionDiscounts(subId);            // GET  /subscriptions/:id/discounts
easy.removeSubscriptionDiscount(subId, discountId); // DELETE

body is exactly one of:

{ coupon_id: string; subscription_item_id?: string }
| { promotion_code: string; subscription_item_id?: string }

One-time charges

await easy.createOneTimeCharge(subId, {
  price_id: "PR_setup_fee",
  quantity: 1,
  description: "Implementation fee",
  due_date: "2026-06-01",
});

The charge attaches to the subscription's next invoice without changing recurring items.

Metered usage

await easy.reportSubscriptionUsage(subId, {
  subscription_item_id: itemId,
  quantity: 42,
  action: "increment",                  // or "set"
  timestamp: new Date().toISOString(),
  idempotency_key: deliveryEventId,
});

await easy.getSubscriptionUsageSummary(subId, {
  subscription_item_id: itemId,
  from: "2026-04-01",
  to: "2026-04-30",
});

await easy.getSubscriptionUsageReconciliation(subId, {
  subscription_item_id: itemId,
  period_start: "2026-04-01",
  period_end: "2026-04-30",
});

Proration preview

Run a dry-run before applying item changes:

const preview = await easy.getSubscriptionProrationPreview(subId, {
  items: [{ price_id: "PR_higher_tier", quantity: 1 }],
  remove_items: [oldItemId],
  proration_date: new Date().toISOString(),
});

Object shape

SubscriptionData:

FieldTypeNotes
idstring
identity_id / instrument_idstring | string | null
statusSubscriptionStatusTRIALING, ACTIVE, PAST_DUE, CANCELED, UNPAID, PAUSED, INCOMPLETE, INCOMPLETE_EXPIRED.
itemsSubscriptionItem[]Each with price_id, optional price, quantity, metadata.
current_period_start / current_period_endstring | nullISO timestamps.
trial_start / trial_endstring | null
billing_cycle_anchorstring | null
cancel_at / cancel_at_period_end / canceled_at / ended_atvariousCancellation state.
pause_collection{ behavior, resumes_at } | null
latest_invoice_idstring | null
proration_behaviorProrationBehavior | null
credit_balancenumber
pending_updateSubscriptionPendingUpdate | null

Examples

Upgrade with proration preview

const previewed = await easy.getSubscriptionProrationPreview(subId, {
  items: [{ price_id: "PR_pro_yearly", quantity: 1 }],
  remove_items: [currentMonthlyItemId],
});
// Show previewed.data to the user, then commit:
await easy.updateSubscription(subId, {
  items: [{ price_id: "PR_pro_yearly", quantity: 1 }],
  remove_items: [currentMonthlyItemId],
  proration_behavior: "create_prorations",
});

Apply a 3-month coupon

const coupon = await easy.createCoupon({
  duration: "repeating",
  duration_in_months: 3,
  percent_off: 25,
  name: "Q2 promo",
});
await easy.applySubscriptionDiscount(subId, { coupon_id: coupon.data.id });

Idempotent metered usage from a webhook

await easy.reportSubscriptionUsage(subId, {
  subscription_item_id: itemId,
  quantity: 1,
  action: "increment",
  idempotency_key: webhookDeliveryId, // repeat-safe
});

On this page