Initiate a basket with a Limio Offer
This guide shows how to fetch a specific Limio Offer (including by custom attributes) and create a checkout basket pre-loaded with that Offer.
Overview
Purchase Links and standard Offers Pages are great for communicating acquisition journeys where every visitor sees the same public offer.
For win-back, renewal, upsell and other targeted flows, you usually want more control because you already know who the customer is. You might want to send them straight to checkout from an email, your CRM, or your own app instead of dropping them on to a landing page to choose an Offer.
In those cases, you can create a service using Limio APIs that will create and pre-populate a Limio basket for that specific customer before they ever click through. For example, you can:
Decide if they’re eligible for a specific price or offer
Prefill known details (email, account ID, address) so they don’t have to type them
Add extra metadata to the Limio basket (cart) that only exists in your system, like campaign codes or CRM IDs
This gives you a few advantages:
No pricing/eligibility logic in the browser. All rules stay on your side, not in public JavaScript.
Cleaner handoff into checkout. The basket is already built, so the customer lands in a ready to pay state with minimal clicks.
Richer basket data. You can attach custom fields and tracking info up front, instead of trying to stitch it together later.
Prerequisites
Access to the Limio Commerce API with a valid Bearer token. All requests in this guide use
Authorization: Bearer <YOUR_TOKEN>.A published Offer configured in Limio. If you’re new to Offers, start here: What are Offers and how to configure them?
(Optional but recommended) One or more Custom Attributes on your Offer to help you query the right Offer for a campaign or journey. Learn how to add attributes to templates here.
Limio Shop page with Modular Checkout (Form) to consume the created basket by
id. See the Limio SDK Basket page for how the cart/basket is used in components.
What you’ll build
Fetch Offers (V2) and optionally filter by a custom attribute (e.g., a campaign code) to locate the exact Offer and Version you want.
Initiate a checkout session (basket) with that Offer’s
idandversion. The API returns a basketid.Send the shopper to checkout with the basket
idso your checkout page loads the pre-populated Offer.
Fetch your Offers
Use Get Offers V2 to retrieve standalone Offers. You can retrieve all your offers or use the attributes parameter to fetch only the Offers relevant to your campaign, defined in your Offer template (e.g., campaign_code__limio=WIN001).
Example — fetch offers with a campaign attribute (curl)
curl -s -G \
'https://your-environment.prod.limio.com/api/offers/v2' \
-H 'Authorization: Bearer <YOUR_TOKEN>' \
--data-urlencode 'attributes.campaign_code__limio=WIN001' \
--data-urlencode 'reducedData=true' \
--data-urlencode 'offersSource=published' \
--data-urlencode 'opt.pageSize=10'Notes:
attributes.<YOUR_ATTRIBUTE>limits results to Offers that have this specific attribute valueoffersSource=publishedlimits results to published Offers; usecatalogto return all from your catalog.reducedData=truemakes responses smaller when you only need keys likeid,version,path, etc.
Response (truncated):
{
"hits": 1,
"items": [
{
"id": "fab052ce94fbfd0d3663ec0cb9d977367a593684",
"name": "Offer Digital",
"path": "/offers2/Offer Digital",
"version": "101d166f7386bb9f1c7635412424b51bbe393ccc",
"record_type": "offer"
}
]
}If you’re unfamiliar with configuring Offers and their attributes, see the Offers overview and Templates & Custom Attributes docs.
Initiate the basket with your Offer
Use Create or update a checkout session to create a Limio basket that includes your chosen Offer. At minimum you’ll provide:
order.orderItems[].offerwith the Offeridandversionyou fetched in Step 1order.external_id— your external reference, this can be any random IDorder.country,order.source,order.order_typeOptionally
order.trackingmetadata (e.g.,offers,purchaseCountryCode, CRM IDs) for analytics/CRM linking
Example — initiate a checkout session (curl)
curl -s -X POST \
'https://your-environment.prod.limio.com/api/checkout/initiate' \
-H 'Authorization: Bearer <YOUR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"order": {
"orderItems": [
{
"offer": {
"id": "fab052ce94fbfd0d3663ec0cb9d977367a593684",
"version": "101d166f7386bb9f1c7635412424b51bbe393ccc"
},
"quantity": 1
}
],
"external_id": "WINBACK-2025-000123",
"tracking": {
"offers": ["/offers2/Offer Digital"],
"purchaseCountryCode": "GB",
"accountId": "0017x00000Q9O9qAAF",
"contactId": "0037x00000F58M9AAJ",
"userId": "0057x0000088Oh3AAE"
},
"country": "GB",
"source": "shop",
"order_type": "new"
}
}'Response:
{ "id": "basket-8cf72b2a-eb57-462d-8e55-981c3b5e5364" }The response
idis the basket id for this checkout session. Keep it - you’ll pass it into your shop’s checkout.
Send the customer to checkout with the basket id
Your shop/checkout page (e.g., Modular Checkout built with the Form component) should read the basket id and load the session. A typical pattern is:
https://your-environment-shop.prod.limio.com/checkout?basket=<BASKET_ID>Use the Limio SDK Basket helpers within your component(s) to read and render the basket/cart and present additional parameters you might have added to your Basket object.
For checkout UI, see Component: Form (Modular Checkout) and related guidance on composing a checkout page with subcomponents.
End-to-end example (Node.js)
Below is a minimal Node.js service that finds an Offer by attribute and initiates a basket.
import express from "express";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
const LIMIO_BASE = "https://your-environment.prod.limio.com";
const TOKEN = process.env.LIMIO_TOKEN;
// Find an Offer by custom attribute and initiate a checkout session
app.post("/winback", async (req, res) => {
const { campaignCode, externalId, country = "GB" } = req.body;
// 1) Get Offers V2 filtered by attribute
const offersUrl = new URL(`${LIMIO_BASE}/api/offers/v2`);
offersUrl.searchParams.set(`attributes.campaign_code__limio`, campaignCode);
offersUrl.searchParams.set("offersSource", "published");
offersUrl.searchParams.set("reducedData", "true");
const offersResp = await fetch(offersUrl, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
if (!offersResp.ok) {
const err = await offersResp.text();
return res.status(offersResp.status).send(err);
}
const offers = await offersResp.json();
const offer = offers.items?.[0];
if (!offer) return res.status(404).send("Offer not found");
// 2) Initiate checkout session with the Offer id + version
const initiateResp = await fetch(`${LIMIO_BASE}/api/checkout/initiate`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
order: {
orderItems: [
{
offer: { id: offer.id, version: offer.version },
quantity: 1,
},
],
external_id: externalId, // becomes checkoutId
tracking: { offers: [offer.path], purchaseCountryCode: country },
country,
source: "shop",
order_type: "new",
},
}),
});
if (!initiateResp.ok) {
const err = await initiateResp.text();
return res.status(initiateResp.status).send(err);
}
const { id: basketId } = await initiateResp.json();
// 3) Return a checkout URL for the client/app/email flow
const checkoutUrl = `https://your-environment-shop.prod.limio.com/checkout?basket=${encodeURIComponent(basketId)}`;
res.json({ basketId, checkoutUrl });
});
app.listen(3000);Tips & troubleshooting
Can I page through lots of Offers? Yes—use
opt.all=trueand followqueryMorepointers (from+alias) to retrieve subsequent pages.Published vs catalog: If your org uses Published Offers, set
offersSource=publishedto restrict results to published records.Basket anatomy: To understand what’s inside a basket and how your shop components read it, review the Basket SDK page.
Abandoned baskets: If you’re running remarketing flows, see the Abandoned Baskets API for retrieving in-progress but uncompleted sessions.
Last updated
Was this helpful?