Guide: Initiate a Basket with a Limio 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 carrying the admin scope. 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 complete the order. 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.
Create a checkout basket with that Offer’s
idandversion. The API returns the basketidand a recovery link.Send the shopper to checkout using that recovery link, so they land on a ready-to-pay checkout with the Offer already in the basket.
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. The attribute is a custom attribute that you define in your Offer template (e.g., campaign_code=WIN001). Note that the __limio suffix is reserved for Limio's own attributes, so do not use it when naming your own.
Example — fetch offers with a campaign attribute (curl)
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):
If you’re unfamiliar with configuring Offers and their attributes, see the Offers overview and Templates & Custom Attributes docs.
Create the basket with your Offer
Use Create checkout basket for new subscription to create a Limio basket that includes your chosen Offer. These fields are required:
order.orderItems[].offer— the Offeridandversionyou fetched in Step 1order.external_id— your external reference. It becomes thecheckoutIdof the order, so use something you can trace back to your systemorder.country,order.source,order.order_type("new"here)
And these are optional:
order.tracking— analytics and CRM metadata (offers,purchaseCountryCode, Salesforce IDs). Passingtracking.accountIdalso assigns the basket an owner, which changes how you send the customer to checkout — see belowjourney.checkout— send the customer to a custom checkout page instead of the defaultexpiresAfter— how long the basket stays alive. Defaults to 14 daysTo apply a promo code, create the basket first, then call
POST /api/admin/v2/promo_codewith thebasketIdfrom the response
Example — create a checkout basket (curl)
Response:
recoveryLink— a signed URL, valid 30 days. This is how you send the customer to checkout.assistedCheckoutLink— returned only when you passedtracking.accountId. The example above does, so it gets one.order— the order as Limio resolved it, with real pricing. Worth logging: this is the source of truth, not what you sent.
Send the customer to checkout
Send them to the recoveryLink, appended to your shop domain:
That link does two things a bare basket id cannot: it establishes the shopper’s checkout session in their browser, then redirects them to the checkout page with the basket loaded.
Do not build your own ?basket=<id> URL. Your backend created this basket, so the shopper’s browser has no session for it, and a basket id alone does not create one. The signed recovery link is what carries the session across.
If you passed tracking.accountId, use the assistedCheckoutLink instead. It does the same thing, but also signs the customer in on behalf of that account (an OBO flow), so an agent or a CRM-driven journey lands them straight into an authenticated checkout.
Once they arrive, your checkout page renders the basket as normal. Use the Limio SDK Basket helpers in your components to read the cart and any custom fields you attached.
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, creates a basket, and returns a link you can drop into an email or your CRM.
Tips & troubleshooting
Why not just pass the basket id to my checkout page? Because your backend created the basket, the shopper’s browser has no session for it. The
recoveryLinkestablishes that session and then redirects; a bare id does not.How long does the link last? The signed token in
recoveryLinkandassistedCheckoutLinkis valid for 30 days. The basket itself expires after 14 days unless you setexpiresAfter.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 baskets. It returns a
recoveryLinkfor each one, the same mechanism this guide uses.Renewals: To build a basket for an existing subscription’s renewal rather than a new purchase, use Create checkout basket to renew subscription.
Last updated
Was this helpful?

