Skip to main content
Checkout+ is not enabled by default. To get started, reach out to support@loopreturns.com to enable it for your account.

Overview

Checkout+ is Loop’s order protection product for non-Shopify platforms. It lets you offer order protection to your customers at checkout — covering returns, shipping issues, or both — via a single API call. Your integration calls the Checkout+ API during checkout, receives eligibility and pricing information, and applies the protection charge using your platform’s native mechanism. When a customer accepts protection and completes their order, Loop detects the charge on the order and activates coverage automatically.
When is the Checkout+ API Integration the right fit?Checkout+ API integration is designed for merchants on WooCommerce, BigCommerce, or headless/custom platforms who want to offer order protection at checkout. If you’re on Shopify, Checkout+ is available through Loop’s native Shopify extensions — no custom integration required.

How It Works

  1. Analyze the cart — Your integration sends the customer’s cart to POST /v1/analyze. The API evaluates eligibility rules, calculates the protection price, and returns charge instructions.
  2. Present the offer — If eligible, display the protection offer to the customer using the pricing from the response.
  3. Apply the charge — If the customer accepts, apply the fee to the cart using your platform’s native mechanism (see Platform Integration Guides).
  4. Store the session ID — Save the sessionId from the API response as metadata on the completed order. Loop uses this to link the order back to the analysis.
  5. Order completes — After the order is synced to Loop, we detect the protection fee on the order and activate coverage.

Authentication

Coming Soon

Integration Steps

1

Call the Analyze endpoint

Send the customer’s cart data to POST /v1/analyze whenever the cart changes or the customer reaches checkout.At minimum, include:
  • shopDomain — your shop’s primary domain
  • platformwoocommerce, bigcommerce, or custom
  • cart — with lines, currencyCode, subtotalAmount, totalDiscountAmount, discountedSubtotalAmount, totalTaxAmount, totalAmount, itemCount, and region
Each cart line requires id, productId, quantity, unitPrice, totalPrice, originalTotalPrice, and title.
curl -X POST https://op-api.loopreturns.com/v1/analyze \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -d '{
    "shopDomain": "example.com",
    "platform": "woocommerce",
    "cart": {
      "lines": [
        {
          "id": "line_001",
          "productId": "prod_67890",
          "quantity": 2,
          "unitPrice": { "amount": 2500, "currencyCode": "USD" },
          "totalPrice": { "amount": 5000, "currencyCode": "USD" },
          "originalTotalPrice": { "amount": 5000, "currencyCode": "USD" },
          "title": "Classic T-Shirt"
        }
      ],
      "itemCount": 2,
      "subtotalAmount": 5000,
      "totalDiscountAmount": 0,
      "discountedSubtotalAmount": 5000,
      "totalTaxAmount": 400,
      "totalAmount": 5400,
      "currencyCode": "USD",
      "region": "US"
    }
  }'
2

Handle the response

The response tells you whether the cart is eligible and, if so, how to apply the charge.
{
  "id": "lop_a1b2c3d4e5f6g7h8i9j0",
  "eligible": true,
  "reason": "eligible",
  "mode": "returnCoverage",
  "chargeInstructions": {
    "amount": 298,
    "currencyCode": "USD",
    "method": "fee",
    "label": "order protection"
  },
  "metadata": {
    "priceBreakdown": [
      { "type": "base", "amount": 298, "label": "Return coverage" }
    ],
    "pricingSubtotalUsed": 5000
  }
}
FieldWhat it tells you
eligibleWhether to show the protection offer
reasonWhy the cart is or isn’t eligible (useful for debugging)
chargeInstructions.amountThe fee to charge, in minor currency units
chargeInstructions.labelThe exact label to use when applying the fee
idReference ID to store on the order (see next step)
If eligible is false, chargeInstructions will be null — do not show the offer.
3

Apply the charge

If the customer accepts protection, apply the fee using your platform’s native mechanism. Always use the label from chargeInstructions exactly as returned — Loop identifies protection charges on orders by matching this label.See Platform Integration Guides below for platform-specific instructions.
4

Store the Loop reference ID on the order

Save the id from the API response as metadata on the completed order. Loop uses this to link the order back to the original cart analysis.
PlatformWhere to storeKey
WooCommerceOrder meta_loop_session_id
BigCommerceOrder metafieldloop_session_id
Headless / CustomOrder metadataloop_session_id
This step is required. Without the reference ID on the order, Loop cannot link the order to the analysis and coverage activation will fail.

Checkout+ UI Guidelines

Your checkout UI controls how the protection offer is presented to customers. Loop does not inject any UI — your integration is responsible for rendering the offer, handling customer interaction, and reflecting the charge in the cart total.

Placement

Display the protection offer after the cart summary and before payment. The offer should feel like a natural part of the checkout flow, not a popup or interstitial. Recommended placements:
  • Below the order summary / line items
  • Above the payment method section
  • Near shipping options (especially for shipping protection)
Place the offer where customers are already reviewing costs. This context makes the price feel incremental rather than unexpected.

Offer Display

At minimum, the offer UI should include:
ElementSourceExample
Toggle or checkboxYour UIA switch or checkbox the customer can interact with
Short descriptionYour copy (see Coverage Descriptions below)“Protect your order against returns and shipping issues”
PricechargeInstructions.amount + chargeInstructions.currencyCode”$2.98”
Format the price for display by converting from minor units (e.g., 298$2.98). Use the currencyCode to apply the correct currency symbol and formatting for the customer’s locale.

Default State

Whether the offer is pre-selected (opt-out) or unselected (opt-in) is a business decision. Consider your audience and regional requirements:
ApproachBehaviorWhen to use
Opt-in (default off)Customer actively selects protectionConservative approach; clearer consent signal
Opt-out (default on)Customer must deselect to declineHigher attach rates; check regional consumer protection regulations
Some jurisdictions have regulations around pre-selected charges at checkout. Verify that your default state complies with applicable laws (e.g., EU Consumer Rights Directive, FTC guidelines).

Coverage Descriptions

The mode field in the API response tells you what type of protection is being offered. Use it to tailor the description shown to the customer.
modeWhat it coversSuggested description
returnCoverageReturns”Get hassle-free returns on this order”
shippingProtectionLost, stolen, or damaged packages”Protect your package against loss or damage during shipping”
returnCoverageAndShippingProtectionReturns + shipping issues”Cover your order for easy returns and shipping protection”
These are suggestions — use language that fits your brand voice. The important thing is that the description accurately reflects the coverage type.

Loading and Error States

Your UI should handle the time between calling the API and receiving a response, as well as failures:
StateRecommendation
LoadingHide the offer or show a skeleton/placeholder until the API responds. Do not show stale pricing from a previous cart state.
Error / timeoutHide the offer entirely. Do not block checkout if the Checkout+ API is unavailable.
Ineligible (eligible: false)Hide the offer. Do not show a disabled or grayed-out toggle.
Checkout+ should never block the checkout flow. If the API call fails, times out, or returns an error, proceed with checkout normally — without the protection offer.

Updating on Cart Changes

Re-call the API whenever the cart contents change (items added, removed, or quantities updated). The protection price is based on the cart value, so stale pricing can lead to mismatches between what the customer sees and what Loop expects on the order. When the cart changes:
  1. Call POST /v1/analyze with the updated cart data
  2. Update the displayed price with the new chargeInstructions.amount
  3. Preserve the customer’s opt-in/opt-out selection across updates

Accessibility

Follow standard accessibility practices for the offer UI:
  • Use a native <input type="checkbox"> or an ARIA-equivalent toggle
  • Associate the description and price with the control using <label> or aria-labelledby
  • Ensure the offer is keyboard-navigable and screen-reader friendly
  • Maintain sufficient color contrast for the price and description text

Platform Integration Guides

Each platform has its own mechanism for applying fees and storing metadata. Follow the guide for your platform.

WooCommerce

WooCommerce integrations apply the protection charge as a cart fee using the WC_Cart::add_fee() method.
Applying the charge: Use the amount and label from chargeInstructions to add a fee to the cart. Convert the amount from minor units to major units (divide by 100 for most currencies).
<?php

add_action('woocommerce_cart_calculate_fees', function () {
    if (WC()->session->get('loop_session_eligible')) {
        $amount = WC()->session->get('loop_session_amount');
        $label = WC()->session->get('loop_session_label');

        // $amount is in minor units (cents) — convert to major units
        WC()->cart->add_fee($label, $amount / 100, true);
    }
});
Storing the reference ID: Save the id from the API response as hidden order meta using the _loop_session_id key. The underscore prefix keeps it hidden from the customer-facing order details.
<?php

add_action('woocommerce_checkout_order_created', function ($order) {
    $loop_id = WC()->session->get('loop_session_id');
    if ($loop_id) {
        $order->update_meta_data('_loop_session_id', $loop_id);
        $order->save();
    }
});
Acceptance verification: Loop detects protection acceptance by checking whether the completed order contains a fee line item whose label matches the chargeInstructions.label returned by the API.
DataLocationWritten by
Protection chargeFee line item via WC_Cart::add_fee()Your integration
Loop reference IDOrder meta: _loop_session_idYour integration

BigCommerce

BigCommerce integrations apply the protection charge as an order-level fee using the Checkout Fees API or Orders API.
Checkout+ for BigCommerce requires your store to support the Checkout Fees API. Stores without access to order-level fees cannot use Checkout+. Verify this with your BigCommerce plan before starting your integration.
Applying the charge: Use the BigCommerce Checkout Fees API to add the fee during checkout, or the Orders API to add it at order creation.
# Option 1: Checkout Fees API (during checkout)
curl -X POST https://api.bigcommerce.com/stores/{store_hash}/v3/checkouts/{checkoutId}/fees \
  -H "X-Auth-Token: YOUR_BC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fee": {
      "name": "order protection",
      "amount": 2.98,
      "type": "fixed"
    }
  }'
Storing the reference ID: Store the id from the API response as an order metafield with the key loop_session_id. Acceptance verification: Loop detects protection acceptance by checking whether the completed order contains a fee whose label matches the chargeInstructions.label. BigCommerce also provides the cart_id on the Order object automatically, which Loop can use as a fallback for linking.
DataLocationWritten by
Protection chargeOrder-level fee via Checkout Fees API or Orders APIYour integration
Loop reference IDOrder metafield: loop_session_idYour integration
Cart IDcart_id on the Order objectBigCommerce (automatic)

Headless / Custom

Headless and custom integrations have full flexibility over how the charge is applied and where metadata is stored. The requirements below are the minimum for Loop to detect and link protection purchases.
Applying the charge: Add the protection fee to the order using whatever mechanism your platform provides. The fee amount, currency, and label must match the values in chargeInstructions. Storing the reference ID: Include the id from the API response in your order creation payload, stored as order metadata under the key loop_session_id. Acceptance verification: Loop detects protection acceptance by checking the order for a charge matching the label and amount from chargeInstructions. The reference ID stored on the order links it back to the analysis.
DataLocationWritten by
Protection chargePlatform-specific mechanismYour integration
Loop reference IDOrder metadata: loop_session_idYour integration
Your order data must flow to Loop for order linking and billing. The Loop team will work with you during onboarding to set up order data ingestion for your platform.

Charge Instructions

When the cart is eligible, the response includes a chargeInstructions object that tells your integration exactly how to apply the protection charge.
FieldDescription
amountThe fee amount in minor currency units (e.g., 298 = $2.98 USD)
currencyCodeISO 4217 currency code for the charge
methodThe charge mechanism — fee for all non-Shopify platforms
labelThe display label to use. You must use this exact label so Loop can identify the charge on the completed order.
When the cart is ineligible, chargeInstructions is null.

Acceptance Determination

There is no explicit acceptance or rejection API call. Loop infers whether the customer accepted protection by examining the completed order:
OutcomeHow Loop determines it
AcceptedThe order contains a fee matching the chargeInstructions.label. Coverage is activated and the order is billed.
DeclinedThe order completes without the protection fee. No coverage, no billing.
Not shownThe API returned eligible: false. No offer was presented.
AbandonedThe cart was analyzed but no order was placed. No action needed.
This approach is more reliable than client-reported status because it verifies acceptance from the actual order data.

Error Handling

All error responses use a consistent envelope:
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": {
      "cart.currencyCode": "Required",
      "cart.totalAmount": "Expected number, received string"
    }
  }
}
HTTP StatusError CodeCondition
400invalid_requestMalformed JSON or missing required fields
400validation_errorSchema validation failure — check error.details for per-field errors
401unauthorizedMissing or invalid API key
404shop_domain_not_foundshopDomain not recognized
429rate_limitedPer-merchant rate limit exceeded
500internal_errorUnexpected server error
Every response includes an X-Request-Id header for log correlation. Include this value when contacting support about a specific request.

Idempotency

If you provide a cart.id in the request, the API uses it for idempotent analysis. Repeated calls with the same shopDomain + cart.id combination update the existing analysis rather than creating a new one. This is useful when the customer modifies their cart during checkout — call the API again with the updated cart data and the same cart.id, and the response will reflect the new pricing.
BigCommerce provides a stable cart_id automatically. For WooCommerce and headless platforms, use whatever stable cart identifier your platform provides, if available.

Debugging

Coming Soon

Technical Considerations

ConsiderationRequirement
Monetary valuesAll amounts are in minor currency units (cents). $10.00 = 1000.
Currency codesISO 4217 format (e.g., USD, EUR, GBP).
Cart updatesRe-call the API when the cart changes to get updated pricing.
Additive changesLoop may add new fields to API responses at any time. Build your integration to tolerate unknown fields.

Analyze Cart — API Reference

Full request and response schema for the POST /v1/analyze endpoint.

Loop Anywhere

Push commerce data into Loop from any source — orders, products, customers, and more.