Products
Manage products, prices, and subscription configurations.
The Products API allows you to manage your product catalog. Products represent items or services you sell, and each product can have up to 3 active prices.
Create a product
Create a new product with one or more prices. At least one price is required.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Product name |
description | string | No | Product description |
product_type | string | Yes | one_time, recurring, or usage_based |
images | array | No | List of product image URLs |
is_active | boolean | No | Active status (default: true) |
display_on_storefront | boolean | No | Show on storefront (default: true) |
prices | array | Yes | Array of price objects (see below) |
metadata | object | No | Custom key-value pairs |
fee_type_ids | array | No | Fee type IDs to apply |
Recurring Product Fields:
| Field | Type | Description |
|---|---|---|
failed_payment_action | string | Action on failed payment: pause, cancel, retry |
charge_day | number | Day of month to charge (1-31) |
first_payment_type | string | initial, non_initial, prorated |
trial_enabled | boolean | Enable trial period |
trial_period_days | number | Trial length in days |
Usage-Based Product Fields:
| Field | Type | Description |
|---|---|---|
usage_aggregation | string | sum, max, last_during_period, last_ever |
usage_unit | string | Unit of measurement (e.g., api_calls) |
Price Object
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Price amount (smallest currency unit) |
currency_code | string | Yes | XOF, USD, EUR |
billing_interval | string | No | day, week, month, year (required for recurring products) |
pricing_model | string | No | standard (default), pay_what_you_want, or tiered |
minimum_amount | number | PWYW | Required when pricing_model is pay_what_you_want |
maximum_amount | number | No | Optional upper bound for pay_what_you_want |
is_default | boolean | No | Set as default price |
metadata | object | No | Optional metadata on the price |
pay_what_you_want requires minimum_amount (and may include maximum_amount). For standard and tiered, omit those unless your integration uses them.
import { LomiSDK } from '@lomi./sdk';
const lomi = new LomiSDK({
apiKey: process.env.LOMI_API_KEY!,
environment: 'live',
});
// One-time product
const product = await lomi.products.create({
name: 'E-book Bundle',
description: 'Complete guide collection',
product_type: 'one_time',
prices: [
{
amount: 25000,
currency_code: 'XOF',
is_default: true,
},
],
display_on_storefront: true,
});
// Subscription product with trial
const subscription = await lomi.products.create({
name: 'Premium Plan',
description: 'Monthly premium access',
product_type: 'recurring',
prices: [
{
amount: 10000,
currency_code: 'XOF',
billing_interval: 'month',
is_default: true,
},
],
trial_enabled: true,
trial_period_days: 14,
failed_payment_action: 'retry',
});
console.log(`Product created: ${product.product_id}`);from lomi import LomiClient
import os
client = LomiClient(
api_key=os.environ["LOMI_API_KEY"],
environment="test"
)
# One-time product
product = client.products.create({
"name": "E-book Bundle",
"description": "Complete guide collection",
"product_type": "one_time",
"prices": [
{
"amount": 25000,
"currency_code": "XOF",
"is_default": True
}
],
"display_on_storefront": True
})
print(f"Product created: {product['product_id']}")curl -X POST "https://api.lomi.africa/products" \
-H "X-API-KEY: $LOMI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "E-book Bundle",
"description": "Complete guide collection",
"product_type": "one_time",
"prices": [
{
"amount": 25000,
"currency_code": "XOF",
"is_default": true
}
],
"display_on_storefront": true
}'List products
Retrieve all products with optional filtering.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
isActive | boolean | Filter by active status |
limit | number | Results per page (default: 15) |
offset | number | Pagination offset (default: 0) |
const products = await lomi.products.list({
isActive: true,
limit: 20,
});products = client.products.list(isActive=True, limit=20)curl -X GET "https://api.lomi.africa/products?isActive=true&limit=20" \
-H "X-API-KEY: $LOMI_API_KEY"Get a product
Retrieve product details including all prices.
const product = await lomi.products.get('prod_abc123...');
console.log(`Default price: ${product.prices.find(p => p.is_default)?.amount}`);product = client.products.get('prod_abc123...')curl -X GET "https://api.lomi.africa/products/prod_abc123..." \
-H "X-API-KEY: $LOMI_API_KEY"Add a price to a product
Add a new price option to an existing product.
Products can have a maximum of 3 active prices. You cannot modify existing prices—create a new one instead.
const price = await lomi.products.addPrice('prod_abc123...', {
amount: 50000,
currency_code: 'XOF',
billing_interval: 'year',
});
console.log(`New price added: ${price.price_id}`);price = client.products.add_price('prod_abc123...', {
"amount": 50000,
"currency_code": "XOF",
"billing_interval": "year"
})curl -X POST "https://api.lomi.africa/products/prod_abc123.../prices" \
-H "X-API-KEY: $LOMI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 50000,
"currency_code": "XOF",
"billing_interval": "year"
}'Set default price
Set a specific price as the default for a product.
const product = await lomi.products.setDefaultPrice('prod_abc123...', 'price_def456...');product = client.products.set_default_price('prod_abc123...', 'price_def456...')curl -X POST "https://api.lomi.africa/products/prod_abc123.../prices/price_def456.../set-default" \
-H "X-API-KEY: $LOMI_API_KEY"Product Object
Returned shapes match the API product resource (see OpenAPI Products). Common fields:
| Field | Type | Description |
|---|---|---|
product_id | string | Unique product identifier |
organization_id | string | Owning organization |
name | string | Product name |
description | string | null | Product description |
product_type | string | one_time, recurring, usage_based |
images | array | null | Product image URLs |
is_active | boolean | Active status |
display_on_storefront | boolean | Storefront visibility |
prices | array | Price objects (price_id, amount, currency_code, billing_interval, pricing_model, minimum_amount, maximum_amount, is_active, is_default, metadata, timestamps) |
fees | array | Associated fee rows (when present) |
environment | string | test or live |
failed_payment_action | string | null | Recurring: pause, cancel, retry |
charge_day | number | null | Recurring charge day (1–31) |
first_payment_type | string | null | initial, non_initial, prorated |
trial_enabled | boolean | Trial enabled |
trial_period_days | number | null | Trial length |
usage_aggregation | string | null | Usage-based products |
usage_unit | string | null | Usage-based products |
metadata | object | null | Custom metadata |
created_at | string | Creation timestamp |
updated_at | string | Last update timestamp |
Error Responses
| Status | Description |
|---|---|
400 | Invalid input or max prices exceeded |
401 | Invalid or missing API key |
404 | Product or price not found |