> ## Documentation Index
> Fetch the complete documentation index at: https://help.lobyco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate offers and bonus with e-commerce

> Show a signed-in customer their coupons in your web shop, apply the discounts at checkout, take payment from their bonus, and record the order.

Your e-commerce platform can give a signed-in customer the same loyalty benefits as a till. They see their coupons, get the discounts those coupons grant, and pay with their bonus balance. Lobyco holds the offers, the coupons and the balance. Your platform's backend reads them, applies them at checkout and records the order. This page is the four pieces in order. Show the coupons, apply the discounts, by Lobyco or by your platform, pay with bonus, and record the order.

> [!WARNING]
>
> **Only the recorded purchase counts the sale.** Pricing a basket and taking a bonus payment record nothing on their own. Send every finished order to the Purchase API with `checkoutType` `Online`. That is what redeems the coupons, earns bonus, moves challenge progress and produces the digital receipt.

## Before you start

* [API authentication](https://help.lobyco.com/integration/get-started/api-authentication) must be working for your platform's backend. Every call on this page is server-to-server.
* The customer is signed in, so your backend has their `memberId`. There is no check-in online, and an anonymous order gets no coupons and no bonus. See [Customers and loyalty cards](https://help.lobyco.com/integration/loyalty-and-membership/customers-and-loyalty-cards.md).
* Your web shop is a store in Lobyco, with a `storeId` of its own or one it shares with a chain. Coupons, payments and purchases all name the store. See [Import chains and stores](https://help.lobyco.com/integration/retail-master-data/import-chains-and-stores.md).
* Marketers limit an offer to checkout types in Nexus. An offer limited to the POS never applies online; an offer with no checkout types applies everywhere. Agree with them which offers the web shop should carry.
* Decide who applies the discounts, below. It decides which of the two middle sections you follow.

## Choose who applies the discounts

```mermaid theme={"system"}
flowchart TD
    Q["Can your platform apply a discount<br/>decided outside it?"]
    Q -->|Yes| L["Lobyco calculates<br/>from the basket"]
    Q -->|No| S["Your platform calculates<br/>from synced offers"]
    L --> R["Record the order,<br/>which redeems the coupons"]
    S --> R
```

| | Lobyco applies the discounts | Your platform applies the discounts |
| - | - | - |
| Your platform | Sends the basket, applies the priced response | Holds a copy of the offers, prices the basket itself |
| Lobyco | Evaluates the coupons and offers, returns the discounts, reserves the coupons | Returns the coupons to apply, nothing more |
| Choose it when | The platform accepts a discount from outside | The platform cannot, as with Instacart and similar providers, so the offer definitions must live in it |

Both routes end the same way: the order is recorded as a purchase, and that redeems the coupons.

## Show the customer's coupons

Whichever route applies the discounts, the customer sees their coupons in the web shop the way they see them in the app.

**Step 1**

### Get the coupons

[GET /v3/customers/\{customerId}/coupons](https://help.lobyco.com/api-reference/promotion-platform/coupons-web-and-mobile-v3/get-v3-customers-customerid-coupons.md)

Pass the web shop's `storeId`, or its `chainId`, so that only the coupons valid there come back. Ask for `includedRelations` `Discount` to show what each coupon is worth. The response is every coupon the customer has that is valid here: assigned, not expired, not yet used. What to show on a coupon, and how, is on [Show offers in your app](https://help.lobyco.com/integration/activities/offers/show-offers-in-your-app.md).

**Step 2**

### Activate a coupon

[POST /v3/customers/\{customerId}/coupons/\{couponId}/activate](https://help.lobyco.com/api-reference/promotion-platform/coupons-web-and-mobile-v3/post-v3-customers-customerid-coupons-couponid-activate.md)

A coupon whose offer is pre-activated is ready at once. Every other coupon needs the customer to activate it, so put an action on the coupon that makes this call. Activation is what makes the coupon available at checkout, online and in store alike.

**Step 3**

### Check the coupon is ready

[GET /v3/customers/\{customerId}/coupons/\{couponId}](https://help.lobyco.com/api-reference/promotion-platform/coupons-web-and-mobile-v3/get-v3-customers-customerid-coupons-couponid.md)

Read the coupon back. An activated coupon carries its `activationTime`, and from then on the checkout calls below find it.

## Let Lobyco apply the discounts

This is the [Discount integration](https://help.lobyco.com/integration/pos-point-of-sale-integrations/discount-integration.md) of the POS, with the web shop as the store and `Online` as the checkout type. Your platform sends the basket; Lobyco returns it priced.

```mermaid theme={"system"}
sequenceDiagram
    participant Shop as Your platform
    participant Lobyco
    Shop->>Lobyco: Price the basket, skipReservation
    Lobyco-->>Shop: Discounts per product and coupon ids
    Note over Shop: Customer goes to checkout
    Shop->>Lobyco: Price the order and reserve
    Lobyco-->>Shop: Final discounts
    Shop->>Lobyco: Reserve the coupons for the checkout
    Note over Shop: Payment, order placed
    Shop->>Lobyco: Record the purchase
    Note over Lobyco: Redeems the coupons
```

**Step 1**

### Price the basket

[POST /v1/discounted-purchases](https://help.lobyco.com/api-reference/promotion-platform/discounts/post-v1-discounted-purchases.md)

Send the basket in the shape of a purchase:

* `receiptId`, the id your order will carry.
* `storeId`, the web shop.
* `memberId`, the signed-in customer.
* `products`, with their prices.
* `checkoutType`, set to `Online`.

Lobyco keeps only the coupons and offers that allow an online checkout, evaluates them against the basket, and returns it priced. While the customer is still shopping, pass `skipReservation=true`: the basket page should not block their coupons. At checkout, call it again without the flag, so Lobyco reserves the coupons that granted a discount.

**Step 2**

### Apply the response

The response repeats the order with the discounts applied. `totalAmount` and each product's `price` are reduced, and `discounts` lists each discount with the `couponIds` that granted it. Show them in the basket and keep the coupon ids for the order. The shape is described step by step on [Discount integration](https://help.lobyco.com/integration/pos-point-of-sale-integrations/discount-integration.md).

**Step 3**

### Hold the coupons through the checkout

[POST /api/v1/customers/\{customerId}/coupons/reserve](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos/post-api-v1-customers-customerid-coupons-reserve.md)

The reservation Lobyco made while pricing lasts 1 minute, which suits a till and not an online checkout with a payment page. Reserve the coupons yourself for the time your checkout takes:

* `couponIds`, from the priced response.
* `reservedBy`, a value that names your platform.
* `reservedUntil`, far enough ahead to cover your payment page. A till reserves for 1 to 5 minutes; an online checkout takes longer.

A coupon reserved this way cannot be used in a store meanwhile.

**Step 4**

### Send the order as a purchase

[POST /v1/purchases](https://help.lobyco.com/api-reference/retail-master-data/purchases/post-v1-purchases.md)

When the order is placed, send it as a purchase, with the `couponIds` from the priced response in its `discounts`. Lobyco redeems the coupons when it loads the purchase, and they drop out of the customer's list. The payload is under [Record the order](#record-the-order).

**Step 5**

### \[Optional] Redeem the coupons at once

[POST /v2/customers/\{customerId}/coupons/redeem](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos/post-v2-customers-customerid-coupons-redeem.md)

The purchase redeems the coupons only when Lobyco loads it. If your platform sends purchases later, in a batch or at fulfilment, redeem the coupons when the order is placed. Send the order's `receiptId` as the `Idempotency-Key` header, and the purchase under the same `receiptId` redeems nothing twice. The rules are on [Coupon redemption at POS](https://help.lobyco.com/integration/pos-point-of-sale-integrations/coupon-redemption-at-pos.md).

## Apply the discounts yourself

When your platform must price the basket itself, it needs two things from Lobyco. The first is a copy of the offers, synced on a schedule. The second is the list of coupons the customer can use, read at checkout.

```mermaid theme={"system"}
sequenceDiagram
    participant Shop as Your platform
    participant Lobyco
    Note over Shop,Lobyco: On a schedule
    Shop->>Lobyco: Get the offers, page by page
    Lobyco-->>Shop: Offers with discounts and products
    Note over Shop,Lobyco: At checkout
    Shop->>Lobyco: Get the coupons to apply
    Lobyco-->>Shop: Usable coupons
    Note over Shop: Price from the synced offers
    Shop->>Lobyco: Reserve the coupons
    Note over Shop: Payment, order placed
    Shop->>Lobyco: Record the purchase
    Note over Lobyco: Redeems the coupons
```

**Step 1**

### Sync the offers

[GET /v3/offers](https://help.lobyco.com/api-reference/promotion-platform/offers-v3/get-v3-offers.md)

Pull the offers on a schedule. Ask for the relations the pricing needs in `includedRelations`:

* `Discount`, the discount rules.
* `Affiliations`, the product and category ids each rule applies to.
* `StoresAndChains`, where the offer is valid.

Filter on `OfferDisplayStatus` `Active` and `Scheduled`. Page with `limit` at 100 or less and `offset`, until a page comes back short. Keep an offer when its `storeIds` or `chainIds` cover the web shop. Keep it only when its discount's `checkoutTypes` is empty or contains `Online`. An empty list means the offer applies at every checkout. Each discount type and its rules are on [Offer and discount types](https://help.lobyco.com/integration/activities/offers). A filter on the date an offer last changed is planned, so that a later sync carries only the changes. Until then, sync the full set.

**Step 2**

### Get the coupons to apply

[GET /v2/customers/\{customerId}/coupons](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos/get-v2-customers-customerid-coupons.md)

At checkout, call the Coupon API with the web shop's `storeId`. It returns the coupons the customer can use now: activated, valid in this store, not yet used. Lobyco has already applied the store and chain filter, so do not filter again. A coupon another system has reserved is listed with `reservedBy` and `reservedUntil`; skip it. Set `includeOfferData=true` to get each coupon's current `discount` with it, and price from that where it differs from your synced copy. Match the rest by `offerId` to the synced offers, and apply the discounts in stacking priority; see [Stacking of coupons](https://help.lobyco.com/integration/pos-point-of-sale-integrations/discount-integration.md#stacking-of-coupons).

This list is not the list from the first section. The customer-facing call returns every coupon the customer has, to show; the Coupon API returns the ones to apply, to price. The two are not interchangeable.

**Step 3**

### Reserve the coupons

[POST /api/v1/customers/\{customerId}/coupons/reserve](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos/post-api-v1-customers-customerid-coupons-reserve.md)

Reserve the coupons you applied for the time the checkout takes, with `reservedBy` naming your platform and `reservedUntil` 10 to 15 minutes ahead. A reserved coupon cannot be used in a store meanwhile.

**Step 4**

### Send the order as a purchase

[POST /v1/purchases](https://help.lobyco.com/api-reference/retail-master-data/purchases/post-v1-purchases.md)

When the order is placed, send it as a purchase, with the `couponIds` you applied in its `discounts`. Lobyco redeems the coupons when it loads the purchase, and the next call for the coupons to apply no longer lists them. The payload is under [Record the order](#record-the-order).

**Step 5**

### \[Optional] Redeem the coupons at once

[POST /v2/customers/\{customerId}/coupons/redeem](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos/post-v2-customers-customerid-coupons-redeem.md)

The purchase redeems the coupons only when Lobyco loads it. If your platform sends purchases later, in a batch or at fulfilment, redeem the coupons when the order is placed. Send the order's `receiptId` as the `Idempotency-Key` header, the `storeId`, each coupon's `value` and the `basketValue`. The purchase under the same `receiptId` redeems nothing twice. The rules are on [Coupon redemption at POS](https://help.lobyco.com/integration/pos-point-of-sale-integrations/coupon-redemption-at-pos.md).

## Pay with bonus

A customer can pay part or all of an order with their bonus balance. Lobyco's Payment Coordinator takes the bonus part; your own payment provider takes the rest.

```mermaid theme={"system"}
sequenceDiagram
    participant Shop as Your platform
    participant Lobyco
    Shop->>Lobyco: Read the balance
    Lobyco-->>Shop: Available balance
    Note over Shop: Customer picks the bonus amount
    Shop->>Lobyco: Create the payment, type Ecommerce
    Lobyco-->>Shop: paymentId, waiting for capture
    Note over Shop: Order placed, fulfilled
    alt Fulfilled
        Shop->>Lobyco: Capture the final amount
        Lobyco-->>Shop: Captured
    else Cancelled
        Shop->>Lobyco: Cancel the payment
        Lobyco-->>Shop: Canceled
    end
```

**Step 1**

### Read the balance

[GET /v1/members/\{memberId}/accounts](https://help.lobyco.com/api-reference/bonus/bonus-accounting/get-v1-members-memberid-accounts.md)

Send `includeBalance=true` and read the `availableBalance` of the active account. Show it at checkout and let the customer choose how much to apply, up to that balance and up to the order total.

**Step 2**

### Create the payment

[POST /v2/payments](https://help.lobyco.com/api-reference/payments/payment-coordinator/post-v2-payments.md)

Send:

* `type`, set to `Ecommerce`.
* `storeId`, the web shop.
* `receiptId`, the order's id.
* `memberId`, the signed-in customer.
* `amount`, the bonus part of the order.
* `operationId`, unique per attempt. Reuse it only when retrying the same attempt, so a retry cannot create a second payment.
* `requestMemberConfirmation`, `false`.

The customer has already chosen the amount in your checkout, so Lobyco confirms the payment with bonus at once. The response carries the `paymentId`, and the payment starts in `WaitingPosCapture`. The amount is reserved on the customer's balance, and nothing has moved yet.

**Step 3**

### Capture when the order is fulfilled

[POST /v2/payments/\{paymentId}/capture](https://help.lobyco.com/api-reference/payments/payment-coordinator/post-v2-payments-paymentid-capture.md)

Capture when the goods are shipped or collected, with the final `amount` and an `operationId`. A smaller amount than reserved is a partial capture, and Lobyco cancels the remainder. Use it when an item was out of stock and the order total fell. The state becomes `Captured`.

Capture before the nightly job runs. It cancels every payment still in `WaitingPosCapture` 3 hours after it was created. If fulfilment takes longer than that, capture the full amount when the order is placed. A refund is of the whole payment, so settle a partly shipped order with a refund and a new payment for the part that shipped. The job is described under [How the purchase checks the payment](https://help.lobyco.com/integration/pos-point-of-sale-integrations/payments.md#how-the-purchase-checks-the-payment).

The purchase can capture for you. When Lobyco loads a purchase whose `LoyaltyApp` amount equals a payment still in `WaitingPosCapture`, it captures the payment. A different amount leaves the payment as it is, so capture it yourself. The rules are under [How the purchase checks the payment](https://help.lobyco.com/integration/pos-point-of-sale-integrations/payments.md#how-the-purchase-checks-the-payment).

**Step 4**

### Check the state

[GET /v2/payments/\{paymentId}](https://help.lobyco.com/api-reference/payments/payment-coordinator/get-v2-payments-paymentid.md)

Read the payment back: `Captured` means the bonus has moved. If the order is cancelled before capture, cancel the payment with [POST /v1/payments/\{paymentId}/cancel](https://help.lobyco.com/api-reference/payments/payment-coordinator/post-v1-payments-paymentid-cancel.md), and the reservation is released. The states, and what each allows, are on [Payments](https://help.lobyco.com/integration/pos-point-of-sale-integrations/payments.md).

## Record the order

[POST /v1/purchases](https://help.lobyco.com/api-reference/retail-master-data/purchases/post-v1-purchases.md)

When the order is placed, send it as a purchase, whichever route priced it. It carries:

* `receiptId`, the order's id, the same one the bonus payment and any explicit redeem call carry.
* `storeId`, the web shop.
* `memberId`, the signed-in customer.
* `checkoutType`, set to `Online`.
* `products`, with their prices before and after discount.
* `discounts`, with the `couponIds` that granted each one. Lobyco redeems these coupons when it loads the purchase, unless an explicit redeem call under the same `receiptId` already did.
* `paymentMethods`, one per method. The bonus payment is one entry with `paymentType` `LoyaltyApp` and the captured amount. Lobyco checks it against the payment under the same `receiptId`, and cancels or refunds a payment recorded another way. See [How the purchase checks the payment](https://help.lobyco.com/integration/pos-point-of-sale-integrations/payments.md#how-the-purchase-checks-the-payment).

The validation rules, and the shape of the discounts and payment methods, are on [Transaction data](https://help.lobyco.com/integration/pos-point-of-sale-integrations/transaction-data.md). The purchase redeems the coupons, earns bonus on the order, moves the customer's challenges, and produces the receipt in [Show digital receipts](https://help.lobyco.com/integration/app-and-web/show-digital-receipts.md).

## Failure and edge cases

If a coupon does not apply, a payment does not complete, or an order changes after it was placed, it is one of these.

* **A coupon was used in a store meanwhile.** Lobyco still accepts the redemption, even past the coupon's redemption limit. The order goes through as priced. The reservation is what stops the in-store use, so keep it live until the order is placed.
* **The checkout outlives the reservation.** Reserve for the time your checkout really takes. If the customer stalls on the payment page, reserve the coupons again with the same `reservedBy` and a later `reservedUntil`. Lobyco refuses a reservation only when another holder's reservation is still live.
* **The order is cancelled.** Before the purchase is sent, release the coupons with the cancel-reservation call. After it, give them back with the cancel-redeem call under the order's `receiptId`. Both are on [Coupon redemption at POS](https://help.lobyco.com/integration/pos-point-of-sale-integrations/coupon-redemption-at-pos.md). Cancel the bonus payment before capture, and refund it after capture with [POST /v1/payments/\{paymentId}/refund](https://help.lobyco.com/api-reference/payments/payment-coordinator/post-v1-payments-paymentid-refund.md).
* **The order is partly fulfilled.** Capture the bonus payment for the final amount. If the purchase is not sent yet, send it with the products that shipped. If it was sent when the order was placed, record the unshipped items as a return with negative prices. Give back their coupons with the cancel-redeem call.
* **The customer returns an item.** Record the return as a purchase with negative prices, as on [Transaction data](https://help.lobyco.com/integration/pos-point-of-sale-integrations/transaction-data.md). Give back the coupons, and refund the bonus payment.
* **Fulfilment takes longer than a day.** The nightly job cancels a bonus payment still waiting for capture, and the customer's balance is released. Capture when the order is placed instead. If part of the order does not ship, refund the payment and create a new one for the part that shipped.
* **The purchase's bonus amount differs from the payment.** Lobyco logs the mismatch and leaves the payment as it is. Capture or cancel it yourself. Send the purchase with the amount you captured, so the two agree.
* **The offers in your copy are stale.** An offer changes in Nexus between two syncs. The `discount` on each coupon from the Coupon API is current, so price from it when it differs from your copy, and sync again.
* **Lobyco is unreachable at checkout.** Pricing and the coupon list have no offline mode. Complete the order without loyalty discounts and without bonus rather than block it, and still record the purchase.
* **The customer is not signed in.** No coupons, no bonus. Record the purchase without a `memberId`, so the sale is still counted.

## API reference

Endpoint documentation: [Coupons (Web & Mobile) V3](https://help.lobyco.com/api-reference/promotion-platform/coupons-web-and-mobile-v3), [Coupons (POS)](https://help.lobyco.com/api-reference/promotion-platform/coupons-pos), [Discounts](https://help.lobyco.com/api-reference/promotion-platform/discounts), [Offers V3](https://help.lobyco.com/api-reference/promotion-platform/offers-v3), [Payment Coordinator](https://help.lobyco.com/api-reference/payments/payment-coordinator), [Bonus accounting](https://help.lobyco.com/api-reference/bonus/bonus-accounting) and [Purchases](https://help.lobyco.com/api-reference/retail-master-data/purchases).

## Related

* [Show offers in your app](https://help.lobyco.com/integration/activities/offers/show-offers-in-your-app.md) — rendering the coupons, and what each type should show.
* [Discount integration](https://help.lobyco.com/integration/pos-point-of-sale-integrations/discount-integration.md) — the pricing Lobyco does, step by step, with the stacking order.
* [Direct coupon service integration](https://help.lobyco.com/integration/pos-point-of-sale-integrations/direct-coupon-service-integration.md) — the POS version of applying the discounts yourself.
* [Coupon redemption at POS](https://help.lobyco.com/integration/pos-point-of-sale-integrations/coupon-redemption-at-pos.md) — the explicit redeem call, reservations, redemption through the purchase, and returns.
* [Payments](https://help.lobyco.com/integration/pos-point-of-sale-integrations/payments.md) — the Payment Coordinator's states, methods and providers.
* [Transaction data](https://help.lobyco.com/integration/pos-point-of-sale-integrations/transaction-data.md) — the purchase payload and its validation.
* [Offer and discount types](https://help.lobyco.com/integration/activities/offers) — the discount rules your platform implements when it prices the basket itself.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.