Skip to main content

Products & Pricing API

The Products & Pricing API allows you to manage your product catalog and pricing structures in your React Native application.

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 IDs
    • limit (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-native";
import { useState, useEffect } from "react";
import { FlatList, View, Text, Image, StyleSheet } from "react-native";

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();
}, []);

return (
<FlatList
data={products}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.card}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.description}>{item.description}</Text>
{!item.active && <Text style={styles.inactive}>Inactive</Text>}
</View>
)}
/>
);
}

const styles = StyleSheet.create({
card: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
name: {
fontSize: 18,
fontWeight: "600",
marginBottom: 8,
},
description: {
fontSize: 14,
color: "#666",
},
inactive: {
fontSize: 12,
color: "#F44336",
marginTop: 4,
},
});

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 Subscription",
description: "Monthly premium subscription with all features",
active: true,
metadata: {
category: "subscription",
tier: "premium",
},
});

Parameters

interface CreateProduct {
name: string;
description?: string;
active?: boolean;
metadata?: Record<string, unknown>;
}

Returns

ApiResponse<ProductData>;

updateProduct

Update an existing product.

const { updateProduct } = useEasy();

const result = await updateProduct("prod_123", {
description: "Updated description",
active: false,
});

Parameters

  • productId (string, required): The ID of the product
  • updates (Partial<CreateProduct>, required): Fields to update

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>;

Price Methods

getProductPrices

Retrieve a list of all prices with optional pagination and filtering.

const { getProductPrices } = useEasy();

const result = await getProductPrices({
limit: 50,
offset: 0,
});

Parameters

  • params (optional)
    • ids (string[], optional): Filter by specific price IDs
    • limit (number): Maximum number of prices to return
    • offset (number): Number of prices to skip for pagination

Returns

ApiResponse<PriceData[]>;

getProductPrice

Retrieve a specific price by ID.

const { getProductPrice } = useEasy();

const result = await getProductPrice("price_123");

Parameters

  • priceId (string, required): The ID of the price

Returns

ApiResponse<PriceData>;

createProductPrice

Create a new price for a product.

const { createProductPrice } = useEasy();

// One-time price
const result = await createProductPrice({
product_id: "prod_123",
unit_amount: 2999, // $29.99 in cents
currency: "USD",
active: true,
description: "One-time purchase",
});

// Recurring price
const recurringPrice = await createProductPrice({
product_id: "prod_123",
unit_amount: 999, // $9.99 in cents
currency: "USD",
recurring: {
interval: "month",
interval_count: 1,
},
active: true,
description: "Monthly subscription",
});

Parameters

interface CreatePrice {
product_id: string;
unit_amount: number; // Amount in cents
currency: string;
recurring?: {
interval: "day" | "week" | "month" | "year";
interval_count: number;
};
active?: boolean;
description?: string;
metadata?: Record<string, unknown>;
}

Returns

ApiResponse<PriceData>;

updateProductPrice

Update an existing price.

const { updateProductPrice } = useEasy();

const result = await updateProductPrice("price_123", {
active: false,
description: "Updated pricing",
});

Parameters

  • priceId (string, required): The ID of the price
  • updates (object, required): Fields to update (only active, metadata, description)

Returns

ApiResponse<PriceData>;

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>;

Complete Example

import { useEasy } from "@easylabs/react-native";
import { useState, useEffect } from "react";
import {
FlatList,
View,
Text,
TouchableOpacity,
StyleSheet,
Alert,
} from "react-native";

function ProductsWithPrices() {
const { getProducts, getProductPrices } = useEasy();
const [products, setProducts] = useState([]);
const [prices, setPrices] = useState({});

useEffect(() => {
loadProducts();
}, []);

const loadProducts = async () => {
try {
const productsResult = await getProducts({ limit: 20 });
setProducts(productsResult.data);

// Load prices for each product
const pricesResult = await getProductPrices({ limit: 100 });
const pricesByProduct = {};

pricesResult.data.forEach((price) => {
if (!pricesByProduct[price.product_id]) {
pricesByProduct[price.product_id] = [];
}
pricesByProduct[price.product_id].push(price);
});

setPrices(pricesByProduct);
} catch (error) {
Alert.alert("Error", "Failed to load products");
}
};

const formatPrice = (price) => {
const amount = (price.unit_amount / 100).toFixed(2);
if (price.recurring) {
return `$${amount}/${price.recurring.interval}`;
}
return `$${amount}`;
};

return (
<FlatList
data={products}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.productCard}>
<Text style={styles.productName}>{item.name}</Text>
<Text style={styles.description}>{item.description}</Text>

{prices[item.id]?.map((price) => (
<TouchableOpacity
key={price.id}
style={styles.priceButton}
onPress={() => {
// Navigate to checkout with this price
}}
>
<Text style={styles.priceText}>{formatPrice(price)}</Text>
{price.description && (
<Text style={styles.priceDescription}>{price.description}</Text>
)}
</TouchableOpacity>
))}
</View>
)}
/>
);
}

const styles = StyleSheet.create({
productCard: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
productName: {
fontSize: 20,
fontWeight: "bold",
marginBottom: 8,
},
description: {
fontSize: 14,
color: "#666",
marginBottom: 12,
},
priceButton: {
padding: 12,
backgroundColor: "#007AFF",
borderRadius: 8,
marginTop: 8,
},
priceText: {
color: "#fff",
fontSize: 16,
fontWeight: "600",
textAlign: "center",
},
priceDescription: {
color: "#fff",
fontSize: 12,
textAlign: "center",
marginTop: 4,
},
});

Type Definitions

ProductData

interface ProductData {
id: string;
name: string;
description?: string;
active: boolean;
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}

PriceData

interface PriceData {
id: string;
product_id: string;
unit_amount: number; // Amount in cents
currency: string;
recurring?: {
interval: "day" | "week" | "month" | "year";
interval_count: number;
};
active: boolean;
description?: string;
metadata?: Record<string, unknown>;
created_at: string;
updated_at: string;
}

Best Practices

1. Display Prices Correctly

Always divide by 100 to display dollar amounts:

<Text>${(price.unit_amount / 100).toFixed(2)}</Text>

2. Handle Recurring Prices

Show billing interval for subscriptions:

const displayPrice = (price) => {
const amount = (price.unit_amount / 100).toFixed(2);
if (price.recurring) {
const { interval, interval_count } = price.recurring;
if (interval_count === 1) {
return `$${amount}/${interval}`;
}
return `$${amount} every ${interval_count} ${interval}s`;
}
return `$${amount}`;
};

3. Cache Product Data

Cache product and price data to reduce API calls:

const [cache, setCache] = useState({});

const getProductWithCache = async (productId) => {
if (cache[productId]) {
return cache[productId];
}

const result = await getProduct(productId);
setCache({ ...cache, [productId]: result.data });
return result.data;
};

Next Steps