Documentation Index
Fetch the complete documentation index at: https://docs.fluveo.com/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks through the full commerce flow: create a product, set a price, and collect payment using a Checkout Session or a shareable Checkout Link.
Overview
The commerce model has four layers:
- Product — what you sell (name, description, images)
- Price — how much it costs (amount, currency, one-time or recurring)
- Checkout Session — a server-driven payment flow for a specific set of line items
- Checkout Link — a shareable, reusable payment URL (no code required)
Step 1: Create a product
curl -X POST https://api.leanrails.com/v1/products \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Ergonomic Standing Desk",
"description": "Height-adjustable bamboo standing desk, 60x30 inches",
"images": ["https://cdn.example.com/desk-hero.jpg"],
"shippable": true,
"metadata": {
"warehouse_sku": "DESK-BAMBOO-60"
}
}'
Response:
{
"id": "prod_8mn4qr7vw2xz",
"object": "product",
"active": true,
"name": "Ergonomic Standing Desk",
"description": "Height-adjustable bamboo standing desk, 60x30 inches",
"images": ["https://cdn.example.com/desk-hero.jpg"],
"default_price": null,
"shippable": true,
"metadata": {
"warehouse_sku": "DESK-BAMBOO-60"
},
"livemode": false,
"created": 1742025600,
"updated": 1742025600
}
You can also create a product with an inline price using default_price_data:
curl -X POST https://api.leanrails.com/v1/products \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Wireless Keyboard",
"default_price_data": {
"currency": "usd",
"unit_amount": 7900
}
}'
Step 2: Create a price
If you did not use default_price_data, create a price separately:
curl -X POST https://api.leanrails.com/v1/prices \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"product": "prod_8mn4qr7vw2xz",
"currency": "usd",
"unit_amount": 49900
}'
Response:
{
"id": "price_3fg6hj9km1np",
"object": "price",
"active": true,
"product": "prod_8mn4qr7vw2xz",
"currency": "usd",
"type": "one_time",
"billing_scheme": "per_unit",
"unit_amount": 49900,
"tax_behavior": "unspecified",
"metadata": {},
"livemode": false,
"created": 1742025610
}
Step 2b: Create product variants (optional)
If your product comes in different configurations (size, color, material), create variants. Each variant is linked to a Price.
Link to an existing price
curl -X POST https://api.leanrails.com/v1/products/prod_8mn4qr7vw2xz/variants \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"title": "Bamboo — 60x30",
"price_id": "price_3fg6hj9km1np",
"sku": "DESK-BAMBOO-60",
"weight": 25000,
"weight_unit": "g"
}'
Create with inline price
curl -X POST https://api.leanrails.com/v1/products/prod_8mn4qr7vw2xz/variants \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"title": "Walnut — 72x30",
"price": 69900,
"currency": "usd",
"sku": "DESK-WALNUT-72"
}'
When you provide price instead of price_id, a Price object is automatically created and linked to the variant.
When creating a product with default_price_data, a hidden default variant (is_default: true) is automatically created and linked to the price. You don’t need to create it manually.
Step 3: Accept payment with a Checkout Session
Create a Checkout Session to collect payment for one or more line items. In payment mode, a PaymentIntent is created automatically.
curl -X POST https://api.leanrails.com/v1/checkout/sessions \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"mode": "payment",
"line_items": [
{
"price": "price_3fg6hj9km1np",
"quantity": 1
}
],
"success_url": "https://yourstore.com/thank-you?session_id={CHECKOUT_SESSION_ID}",
"cancel_url": "https://yourstore.com/cart"
}'
Response:
{
"id": "cs_5ab7cd9ef1gh",
"object": "checkout.session",
"mode": "payment",
"status": "open",
"payment_status": "unpaid",
"ui_mode": "hosted",
"url": "https://checkout.leanrails.com/cs/cs_5ab7cd9ef1gh",
"payment_intent": "pi_2wx4yz6ab8cd",
"currency": "usd",
"amount_subtotal": 49900,
"amount_total": 49900,
"livemode": false,
"created": 1742025620
}
Redirect your customer to the url to complete payment.
Alternative: Use a Checkout Link
For a no-code option, create a reusable Checkout Link that you can share anywhere:
curl -X POST https://api.leanrails.com/v1/checkout_links \
-u "sk_test_xxx:" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"title": "Standing Desk",
"line_items": [
{
"price": "price_3fg6hj9km1np",
"quantity": 1
}
],
"after_completion": {
"type": "redirect",
"redirect": {
"url": "https://yourstore.com/thank-you"
}
}
}'
Response:
{
"id": "cl_4de6fg8hi0jk",
"object": "checkout_link",
"active": true,
"url": "https://checkout.leanrails.com/cl/cl_4de6fg8hi0jk",
"title": "Standing Desk",
"currency": "usd",
"livemode": false,
"created": 1742025630
}
Share the url via email, social media, or embed it on your website.
Step 4: Handle the completion webhook
When payment completes, you receive a checkout.session.completed webhook event:
# Example webhook payload
{
"id": "evt_1abc2def3ghi",
"type": "checkout.session.completed",
"data": {
"object": {
"id": "cs_5ab7cd9ef1gh",
"object": "checkout.session",
"status": "complete",
"payment_status": "paid",
"payment_intent": "pi_2wx4yz6ab8cd",
"amount_total": 49900,
"currency": "usd"
}
}
}
Use this event to fulfill the order, send a confirmation email, or update your database.
Always verify webhook signatures before processing events. See the Webhooks guide for details on signature verification.
Next steps