Skip to main content

Subscriptions API

Manage recurring billing subscriptions with the Easy SDK's comprehensive subscription management system.

info

The Node.js SDK provides full subscription lifecycle management including subscription plans, customer subscriptions, trials, discounts, and automated billing.

Subscription Plans

Subscription plans define the pricing, billing interval, and default settings for subscriptions.

Create a Subscription Plan

import { createClient } from "@easylabs/node";

const easy = await createClient({
apiKey: process.env.EASY_API_KEY!,
});

const plan = await easy.createSubscriptionPlan({
plan_name: "Pro Monthly Plan",
description: "Professional tier with all features",
nickname: "Pro Plan",
amount: 2999, // $29.99 in cents
currency: "USD",
billing_interval: "MONTHLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
trial_defaults: {
interval_type: "DAY",
interval_count: "14",
},
discount_phase_defaults: {
amount: 1000, // $10.00 off in cents
billing_interval_count: 3, // For first 3 billing cycles
},
tags: {
tier: "professional",
features: "all",
},
});

Get Subscription Plans

// Get all plans
const plans = await easy.getSubscriptionPlans({
limit: 20,
offset: 0,
});

// Get specific plans by IDs
const specificPlans = await easy.getSubscriptionPlans({
ids: ["plan_123", "plan_456"],
});

// Get a single plan
const plan = await easy.getSubscriptionPlan("plan_123");

Update a Subscription Plan

const updated = await easy.updateSubscriptionPlan("plan_123", {
plan_name: "Pro Monthly Plan - Updated",
nickname: "Pro Plan v2",
description: "Updated pricing with more features",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: false,
},
});

Customer Subscriptions

Create a Subscription

Subscribe a customer to a plan:

const subscription = await easy.createSubscription({
subscription_plan_id: "plan_456",
buyer_details: {
identity_id: "cust_123",
first_name: "John",
last_name: "Doe",
email: "john@example.com",
phone_number: "+1234567890",
billing_address: {
line1: "123 Main St",
city: "Anytown",
region: "CA",
postal_code: "12345",
country: "US",
},
shipping_address: null,
},
nickname: "Premium Subscription",
start_subscription_at: "2024-01-01T00:00:00Z", // Optional
subscription_details: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
trial_details: {
trial_period_days: 14,
},
discount_phase_details: {
discount_amount: 500, // $5.00 off in cents
discount_duration_in_billing_intervals: 3,
},
},
tags: {
source: "web",
campaign: "holiday-sale",
},
});

Get Subscriptions

// Get all subscriptions (admin)
const allSubscriptions = await easy.getSubscriptions({
limit: 50,
offset: 0,
});

// Get specific subscriptions by IDs
const specificSubscriptions = await easy.getSubscriptions({
ids: ["sub_123", "sub_456", "sub_789"],
});

// Get customer's subscriptions (filtered by context)
const customerSubscriptions = await easy.getCustomerSubscriptions({
limit: 20,
});

// Get a single subscription
const subscription = await easy.getSubscription("sub_123");

Cancel a Subscription

const cancelled = await easy.cancelSubscription("sub_123");

console.log(cancelled.data.state); // "CANCELED"
console.log(cancelled.data.canceled_at); // Cancellation timestamp

Subscription + Checkout Integration

You can create subscriptions through the checkout API as well:

// Checkout with subscription (recurring price)
const result = await easy.checkout({
customer_creation: false,
identity_id: "cust_123",
source: "pi_456",
line_items: [
{ price_id: "price_recurring_789", quantity: 1 }, // Subscription
],
metadata: {
order_type: "subscription",
},
});

// Mix one-time purchases with subscriptions
const mixedResult = await easy.checkout({
customer_creation: false,
identity_id: "cust_123",
source: "pi_456",
line_items: [
{ price_id: "price_onetime_123", quantity: 2 }, // One-time
{ price_id: "price_recurring_456", quantity: 1 }, // Subscription
],
});

Complete Subscription System Example

import { createClient } from "@easylabs/node";
import express from "express";

const app = express();
app.use(express.json());

const easy = await createClient({
apiKey: process.env.EASY_API_KEY!,
});

// Setup subscription plans
async function setupSubscriptionPlans() {
// Create monthly plan
const monthlyPlan = await easy.createSubscriptionPlan({
plan_name: "Pro Monthly",
amount: 2999, // $29.99
currency: "USD",
billing_interval: "MONTHLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
trial_defaults: {
interval_type: "DAY",
interval_count: "14",
},
tags: { tier: "pro" },
});

// Create annual plan
const annualPlan = await easy.createSubscriptionPlan({
plan_name: "Pro Annual",
amount: 29900, // $299.00 (save $60/year)
currency: "USD",
billing_interval: "YEARLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
tags: { tier: "pro", discount: "annual" },
});

return { monthlyPlan, annualPlan };
}

// Subscribe endpoint
app.post("/api/subscribe", async (req, res) => {
try {
const { customerId, planId, email, firstName, lastName } = req.body;

const subscription = await easy.createSubscription({
subscription_plan_id: planId,
buyer_details: {
identity_id: customerId,
first_name: firstName,
last_name: lastName,
email: email,
phone_number: null,
billing_address: null,
shipping_address: null,
},
tags: {
source: "api",
},
});

res.json({ success: true, subscription: subscription.data });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

// Get customer subscriptions endpoint
app.get("/api/subscriptions/:customerId", async (req, res) => {
try {
const subscriptions = await easy.getCustomerSubscriptions({
limit: 50,
});

// Filter by customer (or use identity context)
const customerSubs = subscriptions.data.filter(
(sub) => sub.linked_to === req.params.customerId,
);

res.json({ success: true, subscriptions: customerSubs });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

// Cancel subscription endpoint
app.post("/api/subscriptions/:id/cancel", async (req, res) => {
try {
const canceled = await easy.cancelSubscription(req.params.id);

res.json({ success: true, subscription: canceled.data });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

// List available plans endpoint
app.get("/api/plans", async (req, res) => {
try {
const plans = await easy.getSubscriptionPlans({ limit: 50 });

res.json({ success: true, plans: plans.data });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

app.listen(3000);

Best Practices

Trial Periods

Configure trial periods at the plan level or per-subscription:

// Plan-level trial (applies to all subscriptions)
const planWithTrial = await easy.createSubscriptionPlan({
plan_name: "Pro with Trial",
amount: 2999,
currency: "USD",
billing_interval: "MONTHLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
trial_defaults: {
interval_type: "DAY",
interval_count: "30",
},
});

// Per-subscription trial override
const subscriptionWithTrial = await easy.createSubscription({
subscription_plan_id: "plan_123",
buyer_details: {
/* ... */
},
subscription_details: {
trial_details: {
trial_period_days: 7, // Custom trial length
},
},
});

Promotional Discounts

Set up discount phases for promotional pricing:

const planWithDiscount = await easy.createSubscriptionPlan({
plan_name: "Pro with Discount",
amount: 2999,
currency: "USD",
billing_interval: "MONTHLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
discount_phase_defaults: {
amount: 1500, // $15.00 off
billing_interval_count: 6, // For first 6 months
},
tags: {
promotion: "summer-sale",
},
});

Subscription State Tracking

Monitor subscription states:

async function checkSubscriptionStatus(subscriptionId: string) {
const subscription = await easy.getSubscription(subscriptionId);

switch (subscription.data.state) {
case "ACTIVE":
console.log("Subscription is active");
break;
case "PAUSED":
console.log("Subscription is paused");
break;
case "CANCELED":
console.log("Subscription was canceled");
console.log("Canceled at:", subscription.data.canceled_at);
break;
case "EXPIRED":
console.log("Subscription has expired");
break;
}

console.log("Next billing date:", subscription.data.next_billing_date);
console.log(
"Successful payments:",
subscription.data.total_successful_payments,
);
console.log("Failed payments:", subscription.data.total_failed_payments);
}

Failed Payment Handling

Handle failed subscription payments:

async function handleFailedPayment(subscriptionId: string) {
const subscription = await easy.getSubscription(subscriptionId);

if (subscription.data.last_payment_status === "FAILED") {
console.log("Last payment failed");
console.log("Failed payments:", subscription.data.total_failed_payments);
console.log("Balance due:", subscription.data.total_balance_amount);

// Implement retry logic or notify customer
// You might want to:
// 1. Send email notification
// 2. Attempt retry with backup payment method
// 3. Cancel after too many failures
}
}

Plan Upgrades/Downgrades

Manage subscription plan changes:

async function changeSubscriptionPlan(
currentSubscriptionId: string,
newPlanId: string,
) {
// 1. Cancel current subscription
await easy.cancelSubscription(currentSubscriptionId);

// 2. Get current subscription details
const oldSubscription = await easy.getSubscription(currentSubscriptionId);

// 3. Create new subscription with same buyer details
const newSubscription = await easy.createSubscription({
subscription_plan_id: newPlanId,
buyer_details: oldSubscription.data.buyer_details,
tags: {
previous_subscription: currentSubscriptionId,
change_type: "plan_upgrade",
},
});

return newSubscription;
}

Recurring Price Integration

Link subscription plans to recurring prices for checkout:

// 1. Create a product
const product = await easy.createProduct({
name: "Premium Service",
active: true,
});

// 2. Create a subscription plan
const plan = await easy.createSubscriptionPlan({
plan_name: "Premium Monthly",
amount: 4999,
currency: "USD",
billing_interval: "MONTHLY",
billing_defaults: {
collection_method: "BILL_AUTOMATICALLY",
send_invoice: true,
send_receipt: true,
},
});

// 3. Create a recurring price linked to the plan
const recurringPrice = await easy.createPrice({
product_id: product.data.id,
recurring: true,
finix_subscription_plan_id: plan.data.id,
active: true,
tax_behavior: "INCLUSIVE",
description: "Monthly subscription",
});

// 4. Use the price in checkout to create subscription
const checkout = await easy.checkout({
customer_creation: false,
identity_id: "cust_123",
source: "pi_456",
line_items: [{ price_id: recurringPrice.data.id, quantity: 1 }],
});

Next Steps