Products & Pricing API
The Products & Pricing API allows you to manage your product catalog and pricing structures.
Product Methods
getProducts
Retrieve a list of all products with optional pagination and filtering.
const { getProducts } = useEasy();
// Get all products
const allProducts = await getProducts({
limit: 50,
offset: 0,
});
// Get specific products by ID
const result = await getProducts({
ids: ["prod_123", "prod_456"],
});
Parameters
params(optional)ids(string[], optional): Filter by specific product IDslimit(number): Maximum number of products to return (default: 10, max: 100)offset(number): Number of products to skip for pagination
Returns
ApiResponse<ProductData[]>;
Example
import { useEasy } from "@easylabs/react";
import { useState, useEffect } from "react";
function ProductCatalog() {
const { getProducts } = useEasy();
const [products, setProducts] = useState([]);
useEffect(() => {
const fetchProducts = async () => {
try {
const result = await getProducts({ limit: 50 });
setProducts(result.data);
} catch (error) {
console.error("Failed to fetch products:", error);
}
};
fetchProducts();
}, [getProducts]);
return (
<div className="product-grid">
{products.map((product) => (
<div key={product.id} className="product-card">
<h3>{product.name}</h3>
<p>{product.description}</p>
</div>
))}
</div>
);
}
getProduct
Retrieve a specific product by ID.
const { getProduct } = useEasy();
const result = await getProduct("prod_123");
const product = result.data;
Parameters
productId(string, required): The ID of the product to retrieve
Returns
ApiResponse<ProductData>;
createProduct
Create a new product.
const { createProduct } = useEasy();
const result = await createProduct({
name: "Premium Plan",
description: "Access to all premium features",
active: true,
metadata: {
features: ["feature1", "feature2"],
},
});
Parameters
params(required)name(string, required): Product namedescription(string, optional): Product descriptionactive(boolean, optional): Whether the product is active (default: true)metadata(object, optional): Additional custom data
Returns
ApiResponse<ProductData>;
Example
import { useEasy } from "@easylabs/react";
import { useState } from "react";
function CreateProductForm() {
const { createProduct } = useEasy();
const [formData, setFormData] = useState({
name: "",
description: "",
active: true,
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const result = await createProduct(formData);
console.log("Product created:", result.data.id);
} catch (error) {
console.error("Failed to create product:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Product Name"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
required
/>
<textarea
placeholder="Description"
value={formData.description}
onChange={(e) =>
setFormData({ ...formData, description: e.target.value })
}
/>
<label>
<input
type="checkbox"
checked={formData.active}
onChange={(e) =>
setFormData({ ...formData, active: e.target.checked })
}
/>
Active
</label>
<button type="submit">Create Product</button>
</form>
);
}
updateProduct
Update an existing product.
const { updateProduct } = useEasy();
const result = await updateProduct("prod_123", {
name: "Updated Product Name",
active: false,
});
Parameters
productId(string, required): The ID of the product to updateparams(required)name(string, optional): New product namedescription(string, optional): New descriptionactive(boolean, optional): New active statusmetadata(object, optional): Updated metadata
Returns
ApiResponse<ProductData>;
archiveProduct
Archive a product (soft delete).
const { archiveProduct } = useEasy();
const result = await archiveProduct("prod_123");
Parameters
productId(string, required): The ID of the product to archive
Returns
ApiResponse<ProductData>;
Archiving a product will also deactivate all associated prices. Active subscriptions will continue, but no new subscriptions can be created with the archived product's prices.
Price Methods
getProductPrices
Retrieve a list of all prices with optional filtering.
const { getProductPrices } = useEasy();
// Get all prices
const allPrices = await getProductPrices({
limit: 50,
offset: 0,
});
// Get specific prices by ID
const result = await getProductPrices({
ids: ["price_123", "price_456"],
});
Parameters
params(optional)ids(string[], optional): Filter by specific price IDslimit(number): Maximum number of prices to returnoffset(number): Number of prices to skip for pagination
Returns
ApiResponse<PriceData[]>;
Example
import { useEasy } from "@easylabs/react";
import { useState, useEffect } from "react";
function PricingOptions() {
const { getProductPrices } = useEasy();
const [prices, setPrices] = useState([]);
useEffect(() => {
const fetchPrices = async () => {
try {
const result = await getProductPrices({ limit: 50 });
setPrices(result.data);
} catch (error) {
console.error("Failed to fetch prices:", error);
}
};
fetchPrices();
}, [getProductPrices]);
return (
<div>
{prices.map((price) => (
<div key={price.id} className="price-option">
<h4>${(price.unit_amount / 100).toFixed(2)}</h4>
{price.recurring && <span>per {price.recurring.interval}</span>}
</div>
))}
</div>
);
}
getProductPrice
Retrieve a specific price by ID.
const { getProductPrice } = useEasy();
const result = await getProductPrice("price_123");
const price = result.data;
Parameters
priceId(string, required): The ID of the price to retrieve
Returns
ApiResponse<PriceData>;
createProductPrice
Create a new price for a product.
const { createProductPrice } = useEasy();
const result = await createProductPrice({
product_id: "prod_123",
currency: "USD",
unit_amount: 2999, // $29.99
recurring: {
interval: "month",
interval_count: 1,
},
});
Parameters
params(required)product_id(string, required): Product IDcurrency(string, required): Three-letter ISO currency codeunit_amount(number, required): Price in centsrecurring(object, optional): Recurring billing configurationinterval('day' | 'week' | 'month' | 'year'): Billing intervalinterval_count(number): Number of intervals between billings
active(boolean, optional): Whether the price is active (default: true)metadata(object, optional): Additional custom data
Returns
ApiResponse<PriceData>;
Example
import { useEasy } from "@easylabs/react";
import { useState } from "react";
function CreatePriceForm({ productId }) {
const { createProductPrice } = useEasy();
const [amount, setAmount] = useState("");
const [interval, setInterval] = useState("month");
const [isRecurring, setIsRecurring] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
try {
const priceData = {
product_id: productId,
currency: "USD",
unit_amount: Math.round(parseFloat(amount) * 100),
};
if (isRecurring) {
priceData.recurring = {
interval: interval,
interval_count: 1,
};
}
const result = await createProductPrice(priceData);
console.log("Price created:", result.data.id);
} catch (error) {
console.error("Failed to create price:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="number"
placeholder="Price (USD)"
value={amount}
onChange={(e) => setAmount(e.target.value)}
step="0.01"
min="0"
required
/>
<label>
<input
type="checkbox"
checked={isRecurring}
onChange={(e) => setIsRecurring(e.target.checked)}
/>
Recurring
</label>
{isRecurring && (
<select value={interval} onChange={(e) => setInterval(e.target.value)}>
<option value="day">Daily</option>
<option value="week">Weekly</option>
<option value="month">Monthly</option>
<option value="year">Yearly</option>
</select>
)}
<button type="submit">Create Price</button>
</form>
);
}
updateProductPrice
Update a price's metadata, description, or active status.
const { updateProductPrice } = useEasy();
const result = await updateProductPrice("price_123", {
active: false,
metadata: {
deprecated: true,
},
});
Parameters
priceId(string, required): The ID of the price to updateparams(required)active(boolean, optional): New active statusdescription(string, optional): New descriptionmetadata(object, optional): Updated metadata
Returns
ApiResponse<PriceData>;
You cannot change the amount or billing interval of an existing price. To change pricing, create a new price and deactivate the old one.
archiveProductPrice
Archive a price (soft delete).
const { archiveProductPrice } = useEasy();
const result = await archiveProductPrice("price_123");
Parameters
priceId(string, required): The ID of the price to archive
Returns
ApiResponse<PriceData>;
Type Definitions
Product
interface Product {
id: string;
name: string;
description?: string;
active: boolean;
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}
Price
interface Price {
id: string;
product_id: string;
active: boolean;
currency: string;
unit_amount: number;
recurring?: {
interval: "day" | "week" | "month" | "year";
interval_count: number;
};
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}
Pricing Patterns
One-Time Payments
await createProductPrice({
product_id: "prod_123",
currency: "USD",
unit_amount: 4999, // $49.99 one-time
});
Monthly Subscription
await createProductPrice({
product_id: "prod_123",
currency: "USD",
unit_amount: 2999, // $29.99/month
recurring: {
interval: "month",
interval_count: 1,
},
});
Annual Subscription
await createProductPrice({
product_id: "prod_123",
currency: "USD",
unit_amount: 29999, // $299.99/year
recurring: {
interval: "year",
interval_count: 1,
},
});
Quarterly Billing
await createProductPrice({
product_id: "prod_123",
currency: "USD",
unit_amount: 7999, // $79.99 every 3 months
recurring: {
interval: "month",
interval_count: 3,
},
});
Best Practices
- Create multiple prices: Offer monthly/annual options for subscriptions
- Use descriptive metadata: Track pricing tiers and features
- Don't delete prices: Archive them instead to preserve history
- Version your pricing: Create new prices for price changes
- Test with cents: Always test pricing calculations with cent amounts