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.

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

  1. Fetch Offers (V2) and optionally filter by a custom attribute (e.g., a campaign code) to locate the exact Offer and Version you want.

  2. Initiate a checkout session (basket) with that Offer’s id and version. The API returns a basket id.

  3. Send the shopper to checkout with the basket id so 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 value

  • offersSource=published limits results to published Offers; use catalog to return all from your catalog.

  • reducedData=true makes responses smaller when you only need keys like id, 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[].offer with the Offer id and version you fetched in Step 1

  • order.external_id — your external reference, this can be any random ID

  • order.country, order.source, order.order_type

  • Optionally order.tracking metadata (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 id is 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 paramets 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=true and follow queryMore pointers (from + alias) to retrieve subsequent pages.

  • Published vs catalog: If your org uses Published Offers, set offersSource=published to 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?