Sell products
Show your Lahuta products and collections on your own website, and send buyers to a checkout page for their basket.
Use these endpoints to build a shop on your own website from the products you manage in Lahuta. Your site shows the products and keeps the basket. When the buyer is ready, you open a checkout and send them to it. Lahuta's checkout page takes care of delivery, address, coupon and payment, and the order lands in your dashboard like any other.
| You want to | Use |
|---|---|
| List your products | GET /v1/products |
| Show one product with its options and prices | GET /v1/products/{slug} |
| List collections, or show one with its products | GET /v1/collections, GET /v1/collections/{slug} |
| Send a buyer to pay for a basket | POST /v1/products/checkouts |
| Find out what happened to that checkout | GET /v1/products/checkouts/{checkoutId} |
You need a connected Stripe account to sell anything that costs money. See Get paid.
Show your products
GET /v1/products returns every product on sale, in one response. Each item has what a product card needs:
curl https://api.lahuta.org/v1/products \
-H "X-Api-Key: $LAHUTA_API_KEY"{
"items": [
{
"id": "0197a8b1-4f20-7c3e-9d15-2a6e8b1f4c73",
"slug": "speckled-mug",
"name": "Speckled mug",
"category": "handmade",
"image": {
"id": "0197a8b1-4f2b-7a90-8c41-5e3d9f2b6a18",
"type": "image",
"url": "https://media.lahuta.io/images/0197a3c2-5b1e-7d40-9f2a-3c8e1b6d4f70/0197a8b1-4f2b-7a90-8c41-5e3d9f2b6a18.jpg",
"alt": "Speckled stoneware mug",
"width": 1200,
"height": 1200,
"thumbnail": null
},
"fromCents": 3200,
"toCents": 3800
}
]
}fromCents and toCents are the lowest and highest variant prices, so you can show "$32 to $38".
For a product page, GET /v1/products/{slug} adds the description, every photo, the options and the variants:
{
"slug": "speckled-mug",
"name": "Speckled mug",
"descriptionHtml": "<p>Wheel-thrown stoneware, dishwasher safe.</p>",
"fulfillment": {
"_tag": "physical",
"shipping": { "mode": "flat_rate", "flatAmountCents": 800 },
"pickup": null
},
"options": [
{
"id": "0197a8b2-0a11-7e4c-8b92-3f5d1c7a6e20",
"name": "Size",
"values": [
{ "id": "0197a8b2-0a12-7b05-9c3e-6a1f8d2b4c91", "name": "12 oz" },
{ "id": "0197a8b2-0a13-7d68-a0f4-1e9b5c3d7a02", "name": "16 oz" }
]
}
],
"variants": [
{
"id": "0197a8b2-0b40-7f21-8e6d-4c2a9b1f5e37",
"title": "12 oz",
"sku": "MUG-SPK-12",
"priceCents": 3200,
"compareAtCents": null,
"optionValueIds": ["0197a8b2-0a12-7b05-9c3e-6a1f8d2b4c91"],
"image": null
}
]
}The response is trimmed here. It also has media, specifications, category and seller, with your pickup address and free shipping threshold when you have them.
Every product has at least one variant, even without options. Variants are what a buyer puts in the basket. Keep the variant ids for the checkout.
Collections work the same way: GET /v1/collections lists them with a name and image, and GET /v1/collections/{slug} returns one with its products.
Send the buyer to checkout
When the buyer is ready to pay, open a checkout with their basket and redirect them to the url you get back.
curl -X POST https://api.lahuta.org/v1/products/checkouts \
-H "X-Api-Key: $LAHUTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"lines": [
{ "variantId": "0197a8b2-0b40-7f21-8e6d-4c2a9b1f5e37", "quantity": 2 }
],
"successUrl": "https://northsidepottery.com/shop/thanks",
"cancelUrl": "https://northsidepottery.com/shop/cart"
}'{
"checkoutId": "0197b31c-7a05-7e92-8b4d-1c6f3a9e2d58",
"url": "https://lahuta.org/checkout/0197b31c-7a05-7e92-8b4d-1c6f3a9e2d58",
"expiresAt": "2026-09-26T16:40:02.117Z"
}| Field | Required | What it does |
|---|---|---|
lines | Yes | 1 to 50 lines, each a variantId and a quantity from 1 to 999 |
couponCode | No | A coupon code to apply to the basket |
buyer | No | Prefills the buyer's name, email and phone. The buyer can change them on the page |
address | No | Prefills the shipping address. The buyer confirms it on the page |
successUrl | No | Where the buyer can continue to after paying |
cancelUrl | No | Where the checkout page's back button goes |
orgSlug | No | Sell another organization's products. See below |
What the buyer sees:
- The checkout page at
url, with your organization's name, a Back to Northside Pottery button that goes tocancelUrl, the basket, delivery options and payment. - After paying, Lahuta's order page at
lahuta.org/orders/<shortCode>, with a Continue to northsidepottery.com button. It goes to yoursuccessUrlwith?order=<shortCode>added, so your thank-you page knows which order came back.
Always send both URLs. Without successUrl, the order page offers to continue shopping on Lahuta instead of on your site.
Nothing is reserved or charged until the buyer submits the page. The link works for 24 hours, until expiresAt. An abandoned checkout needs no cleanup.
Check what happened
There are no webhooks. To know whether a checkout was paid, ask for it, for example when the buyer lands on your thank-you page:
curl https://api.lahuta.org/v1/products/checkouts/0197b31c-7a05-7e92-8b4d-1c6f3a9e2d58 \
-H "X-Api-Key: $LAHUTA_API_KEY"{
"checkoutId": "0197b31c-7a05-7e92-8b4d-1c6f3a9e2d58",
"status": "ordered",
"expiresAt": "2026-09-26T16:40:02.117Z",
"order": {
"orderId": "0197b320-11d4-7a36-9e08-5b2c7f1d3a64",
"shortCode": "Xq84Tn",
"status": "confirmed"
}
}status | order.status | Meaning |
|---|---|---|
open | none | The buyer hasn't submitted the page yet |
ordered | pending | The order is placed and waiting for Stripe to confirm the payment. Ask again in a few seconds |
ordered | confirmed | Paid, or free. Show the thank-you message |
ordered | cancelled or expired | The order didn't go through |
expired | none | The link's 24 hours passed without an order |
Confirmation can arrive a little after the buyer does, so poll every few seconds while you see open or pending, and stop after a minute or so. Whether or not your site checks, the order shows up in Commerce → Product orders like any other order.
Sell another organization's products
Set orgSlug to another organization's slug to open a checkout for their products, for example a neighboring studio's tools that you recommend. That organization must be listed on Discover. They're the seller: they fulfill the order and keep the money, and the order records that your organization sent the buyer. All lines must be their variants, and the Org API only lists your own products, so get the variant ids from them. See Referrals.
Services
GET /v1/services and GET /v1/services/{slug} return the services you offer, like Northside Pottery's custom dinnerware commissions, with their tiers and prices. Buying a service happens on its Lahuta page, lahuta.org/services/<your-org>/<service slug>, so link there from your site.
Errors
| Error | When |
|---|---|
404 NotFound | The product, collection or checkout doesn't exist, or orgSlug names nobody |
409 LineUnavailable | A variant isn't found, isn't on sale, belongs to another seller, or needs a shipping weight. variantId and reason say which |
409 Conflict | orgSlug names an organization that isn't listed on Discover |
409 PaymentsNotReady | The basket costs money and the seller's Stripe account can't take payments yet |
429 TooManyRequests | Over 300 checkouts this hour, counted together with POST /v1/checkouts. See Rate limits |
See Products in the API reference for every field.