Skip to content

Check products and prices

Use active items when Stripe products or prices represent plans, billing intervals, tiers, or add-ons. Strent returns Stripe identifiers instead of inventing a second plan model.

Use the Node SDK helper when one Stripe product represents the plan:

const hasProPlan = await strent.activeItems.hasProduct({
customer: account.stripeCustomerId,
product: "prod_pro",
});

Any active item with that product matches, regardless of its price. The helper shares the saved active-item list: positives can be reused for less than 5 minutes, while missing products are checked with Strent. Eligible availability failures can use a saved positive less than 1 hour old, with a warning. Use cache: false when your application needs immediate revocation.

hasProduct sends a request whenever the product is missing from the saved list. A chain such as hasProduct(enterprise) || hasProduct(business) || hasProduct(pro) therefore costs one request per absent product, which is every request for a free customer. When you check more than one product or price, read the list once and resolve in memory:

const PLAN_PRODUCTS = [
["enterprise", "prod_enterprise"],
["business", "prod_business"],
["pro", "prod_pro"],
] as const;
const { data: items } = await strent.activeItems.list({
customer: account.stripeCustomerId,
});
const productIds = new Set(items.map((item) => item.price.product.id));
const priceIds = new Set(items.map((item) => item.price.id));
const plan =
PLAN_PRODUCTS.find(([, productId]) => productIds.has(productId))?.[0] ??
"free";
const billsAnnually = priceIds.has(process.env.STRIPE_PRO_ANNUAL_PRICE_ID!);

Product IDs are usually the more stable choice for plan identity. Price IDs are useful when access depends on a specific billing variant.

Use list when quantity, subscription, or price lookup keys matter:

const { data: items } = await strent.activeItems.list({
customer: account.stripeCustomerId,
});
const seats = items
.filter((item) => item.price.product.id === "prod_seats")
.reduce((total, item) => total + (item.quantity ?? 0), 0);

Each item includes the Stripe subscription item ID, subscription ID, price ID, optional price lookup key, product ID, and quantity.

Prefer catalog identifiers over display copy

Section titled “Prefer catalog identifiers over display copy”

Names and labels change. Base durable application rules on Stripe IDs or deliberately managed lookup keys, then keep those identifiers in one domain-level mapping:

export const billingCatalog = {
proProduct: "prod_pro",
annualProPrice: process.env.STRIPE_PRO_ANNUAL_PRICE_ID!,
} as const;

This keeps billing vocabulary at one seam and makes catalog changes reviewable.