Integrating with Extend's Offers API

Overview

Extend's Offers APIs let you retrieve real-time protection offer data—pricing, plan details, and marketing content—so you can present Product Protection and Shipping Protection offers anywhere in your customer's purchase journey.

There are two complementary sets of endpoints:

ProductEndpointsDownstream
Product ProtectionPOST /offers or GET /offersLeads → Orders / Orders Upsert → Contracts
Shipping ProtectionGET /shipping-offers/config, GET /shipping-offers/config/marketing, POST /shipping-offers/quotesOrders / Orders Upsert → Contracts

Both products follow the same high-level pattern: fetch offers → add to cart → report the sale → contracts are created.

📘

Before using these endpoints, make sure you've completed the setup in Getting Started with Extend's API, including environment configuration, authentication, and header requirements.

When to Use the SDK vs. the API

Extend provides a Client Offers SDK that renders fully optimized, pre-built offer components (iFrames) with Extend branding, messaging, and pricing already configured. The SDK is the fastest path to go live and automatically benefits from Extend's Intelligent Offer Engine optimizations.

Use the Offers API directly when you need to:

  • Build a fully custom offer UI that matches your store's design system.
  • Integrate offers into a native mobile app, server-rendered page, or headless storefront.
  • Combine offer data with other business logic before rendering.
📘

Tip: Even when using a custom UI, the API response includes a marketing object with pre-configured messaging and imagery. Leveraging this content ensures brand-compliant, optimized offers without additional design work.


Product Protection Offers

How It Works

  1. Fetch offers — Call the Offers API with the products in the customer's cart or on the PDP to receive plan options, pricing, and marketing content.
  2. Add to cart — When the customer selects a plan, add a warranty SKU to the cart containing the planId, price, and associated product information.
  3. Report the sale — After checkout, send the order to Extend via the Orders or Orders Upsert API.
  4. Contracts created — Extend processes the order and creates protection contracts, triggering a welcome email to the customer.

POST /offers

Accepts a request body with store and product information and returns offer data for all eligible items. This is the recommended approach when you need to fetch offers for multiple products in a single call (e.g., a cart page).

Request

curl --request POST \
  --url {API_HOST}/offers \
  --header 'Accept: application/json;version=2022-02-01' \
  --header 'Content-Type: application/json' \
  --header 'X-Extend-Access-Token: YOUR_ACCESS_TOKEN' \
  --data '{
    "storeId": "str_001",
    "currency": "USD",
    "locale": "en_US",
    "items": [
      {
        "category": "Electronics",
        "productId": "prod-123",
        "purchasePrice": 99999,
        "quantity": 1
      },
      {
        "category": "Electronics",
        "productId": "prod-456",
        "purchasePrice": 49999,
        "quantity": 2
      }
    ]
  }'
FieldTypeRequiredDescription
storeIdstringYesYour unique Extend store identifier.
currencystringYesISO 4217 currency code (e.g., "USD").
localestringNoLocale for language and region (e.g., "en_US").
itemsarrayYesArray of products to get offers for.
items[].categorystringYesMerchant-provided product category.
items[].productIdstringYesUnique product identifier (SKU or reference ID).
items[].purchasePriceintegerYesProduct price in cents (e.g., $999.9999999).
items[].quantityintegerYesQuantity of this product.

GET /offers

Uses query parameters and is useful for fetching offers for a single product on a PDP.

Request

curl --request GET \
  --url '{API_HOST}/offers?storeId=str_001&productId=prod-123&category=Electronics&purchasePrice=99999&locale=en_US&currency=USD' \
  --header 'Accept: application/json;version=2022-02-01' \
  --header 'X-Extend-Access-Token: YOUR_ACCESS_TOKEN'
ParameterTypeRequiredDescription
storeIdstringYesYour unique Extend store identifier.
productIdstringYesUnique product identifier.
categorystringYesMerchant-provided product category.
purchasePriceintegerYesProduct price in cents.
localestringNoLocale code (e.g., "en_US").
currencystringNoISO 4217 currency code.
regionstringNoRegion code, if applicable.

Response Structure

Both endpoints return the same response shape. Below are the key fields you'll use when building your offer UI.

{
  "offerCartId": "ERN:OFC:230e5dae-1d60-4845-80e4-2162a56dfe54",
  "storeId": "str_001",
  "currency": "USD",
  "locale": "en_US",
  "offers": [
    {
      "offerId": "ERN:OFR:1238e5fa-626a-4cf1-92ba-7594ea7139d4",
      "marketing": { "...see Marketing & Surface Versions below..." },
      "plans": {
        "adh": [
          {
            "id": "EXT-ELEC-3Y",
            "price": 14999,
            "title": "3 Year Electronics Protection Plan",
            "contract": {
              "category": "electronics",
              "coverageIncludes": "adh",
              "coverageStarts": "immediate",
              "deductible": 0,
              "termLength": 36
            },
            "url": "https://customers.extend.com/en-US/plan_details/EXT-ELEC-3Y?storeId=str_001",
            "offerPlanId": "ERN:OFP:eb3d0598-632c-4949-a364-b460dd642c9a",
            "imageUrl": "https://sdk.helloextend.com/extend_icon.png"
          }
        ],
        "base": [],
        "recommended": "adh"
      },
      "coveredProducts": [
        {
          "productId": "prod-123",
          "quantity": 1,
          "purchasePrice": 99999
        }
      ]
    }
  ],
  "surfaceVersion": { "...see Marketing & Surface Versions below..." }
}

Key Fields

PathDescription
offers[].plans.adh[]Array of Accidental Damage from Handling (ADH) plans.
offers[].plans.base[]Array of base (non-ADH) plans.
offers[].plans.recommendedWhich plan type Extend recommends ("adh" or "base").
offers[].plans.adh[].idThe planId — include this in the cart and pass it to the Orders API.
offers[].plans.adh[].pricePlan price in cents.
offers[].plans.adh[].titleDisplay title for the plan.
offers[].plans.adh[].urlLink to Extend-hosted plan details page.
offers[].plans.adh[].offerPlanIdReference ID for Extend analytics tracking.
offers[].marketingPre-configured marketing content for each offer surface (PDP, modal, cart, etc.).
surfaceVersionIndicates which offer surface versions are enabled for the store.

Marketing & Surface Versions

The marketing object in each offer is keyed by plan type (e.g., adh) and then by surface type. Each surface contains headlines, subheadlines, coverage bullets, button labels, images, and pricing strings you can render directly.

Surface KeyUse Case
productDetailsPageV2Product Detail Page (PDP) inline offer.
offerTypeModalV2Pop-up modal offer (e.g., triggered on "Add to Cart").
offerTypeCTAV2Cart-level call-to-action banner.
offerTypeCTASimple single-line CTA (e.g., "Add protection for $X").
learnMoreModal"What's covered?" informational modal.
planDetailsFull plan details page content (FAQs, rundown, fine print).
orderConfirmationOfferV1Post-purchase offer on the order confirmation page.

The surfaceVersion object at the root of the response tells you which surfaces are enabled and which content key to use:

"surfaceVersion": {
  "pdp": { "version": "V2", "contentType": "productDetailsPageV2", "enabled": true },
  "offerModal": { "version": "V2", "contentType": "offerTypeModalV2", "enabled": true },
  "offerCart": { "version": "V1", "contentType": "offerTypeCTA", "enabled": true },
  "learnMoreModal": { "version": "V1", "contentType": "learnMoreModal", "enabled": true },
  "orderConfirmationOffer": { "version": "V1", "contentType": "orderConfirmationOfferV1", "enabled": true }
}
📘

Tip: Use surfaceVersion to conditionally render offer components only on surfaces that are enabled for your store.

Offer Placement Best Practices

Product Detail Page (PDP) Display plan options inline near the "Add to Cart" button. Use the productDetailsPageV2 marketing content for headline, subheadline, and term/price buttons. Include a "What's covered?" link that opens the learnMoreModal content.

Modal (Add-to-Cart) When a customer clicks "Add to Cart" without selecting protection, present a modal using offerTypeModalV2. This includes coverage bullets, background imagery, accept/decline buttons, and a link to plan details.

Cart Page Show a cart-level CTA using offerTypeCTAV2 or offerTypeCTA. Group plans by Extend category (e.g., "Indoor Furniture Protection") using the plan title. Display the plan price alongside an "Add" button.

Post-Purchase (Order Confirmation) Use orderConfirmationOfferV1 to present a "Forgot to add protection?" offer on the order confirmation page. This gives customers a second chance to purchase protection after completing their order.

⚠️

Branding requirement:

All custom offer UIs must include Extend branding (logo and/or "Powered by Extend" text), accurate pricing, and a link to plan details and terms. Extend will review custom implementations before launch.


Shipping Protection Offers

How It Works

Shipping Protection (SP) pricing is calculated at the order/cart level rather than per-product. The flow uses three endpoints:

  1. Fetch config — Call /shipping-offers/config and optionally /shipping-offers/config/marketing to get offer display configuration and marketing content.
  2. Get a quote — Call /shipping-offers/quotes with the cart contents to receive a premium (price) and a quoteId.
  3. Add to cart — Represent the shipping protection as a single non-inventory SKU in the cart, priced at the quote's premium.
  4. Report the sale — Include the quoteId as a line item in the Orders or Orders Upsert API call. Extend creates the shipping protection contract.

GET /shipping-offers/config

Returns the offer display configuration for a given store, including marketing text, compliance information, and styling for different attach behaviors (opt-in, opt-out, Extend Complete).

curl --request GET \
  --url '{API_HOST}/shipping-offers/config?storeId=str_001&locale=en-US' \
  --header 'Accept: application/json;version=2022-02-01' \
  --header 'Content-Type: application/json'
ParameterTypeRequiredDescription
storeIdstringYesYour Extend store identifier.
localestringNoLocale for language/region.

The response includes configuration for how the offer should be rendered, including the attach behavior type and associated marketing text.

📘

If your store is not enabled for Shipping Protection, this endpoint returns a 404. This is expected behavior and should be handled gracefully—do not display a shipping protection offer.

GET /shipping-offers/config/marketing

Returns marketing and compliance text specifically for the offer component, including cart offer content (headers, subheaders, coverage bullets) and, if configured, charitable donation content.

curl --request GET \
  --url '{API_HOST}/shipping-offers/config/marketing?storeId=str_001&locale=en-US' \
  --header 'Accept: application/json;version=2022-02-01' \
  --header 'Content-Type: application/json'

POST /shipping-offers/quotes

Calculates the shipping protection premium for the products in the cart and returns a quote.

Request

curl --request POST \
  --url {API_HOST}/shipping-offers/quotes \
  --header 'Accept: application/json;version=2022-02-01' \
  --header 'Content-Type: application/json' \
  --header 'X-Extend-Access-Token: YOUR_ACCESS_TOKEN' \
  --data '{
    "storeId": "str_001",
    "currency": "USD",
    "items": [
      {
        "referenceId": "prod-123",
        "purchasePrice": 99999,
        "productName": "Wireless Headphones",
        "quantity": 1,
        "shippable": true
      },
      {
        "referenceId": "prod-456",
        "purchasePrice": 49999,
        "productName": "Portable Speaker",
        "quantity": 2,
        "shippable": true
      }
    ]
  }'
FieldTypeRequiredDescription
storeIdstringYesYour Extend store identifier.
currencystringYesISO 4217 currency code.
itemsarrayYesArray of cart items.
items[].referenceIdstringYesProduct identifier (SKU, barcode, or database ID).
items[].purchasePriceintegerYesProduct price in cents.
items[].productNamestringNoDisplay name of the product.
items[].quantityintegerYesQuantity in the cart.
items[].shippablebooleanNoWhether the item is physically shipped. Non-shippable items (digital goods, services) are excluded.

Response

{
  "id": "d4f5a6b7-8c9d-0e1f-2a3b-4c5d6e7f8a9b",
  "premium": 299,
  "excluded_products": []
}
FieldDescription
idThe quote ID. Persist this value—it must be passed to the Orders API when reporting the sale.
premiumThe shipping protection price in cents to charge the customer.
excluded_productsProducts not eligible for shipping protection coverage.
⚠️

Important:

If premium is 0 or no id is returned, do not display a shipping protection offer for this cart.

Carrying the quoteId into Orders

When reporting the order to Extend, include the shipping protection as a line item with the quoteId. Note how the same storeId and product identifiers are used consistently with the earlier offers call:

{
  "storeId": "str_001",
  "transactionId": "SO1234",
  "currency": "USD",
  "customer": {
    "name": "Bob Ross",
    "email": "[email protected]",
    "phone": "+1-555-123-4567",
    "shippingAddress": {
      "address1": "456 Customer St",
      "city": "Dallas",
      "province": "TX",
      "postalCode": "75201",
      "countryCode": "US"
    }
  },
  "lineItems": [
    {
      "product": {
        "referenceId": "prod-123",
        "name": "Wireless Headphones",
        "purchasePrice": 99999
      },
      "quantity": 1,
      "purchasePrice": 99999
    },
    {
      "product": {
        "referenceId": "prod-456",
        "name": "Portable Speaker",
        "purchasePrice": 49999
      },
      "quantity": 2,
      "purchasePrice": 49999
    },
    {
      "quoteId": "d4f5a6b7-8c9d-0e1f-2a3b-4c5d6e7f8a9b",
      "purchasePrice": 299,
      "type": "shipping"
    }
  ]
}

Extend processes the shipping protection line item using the quoteId to create the contract and trigger a confirmation email to the customer.

Offer Placement Best Practices

Recommended Placement: Cart / Checkout Display the shipping protection offer in your checkout flow alongside the shipping method selection. This is where customers are already thinking about shipping and delivery, making it the most natural and highest-converting placement.

Representing SP as a Single Non-Inventory SKU Create a single generic SKU in your eCommerce platform (e.g., "extend-shipping-protection") with a display name like "Extend Shipping Protection". This SKU should:

  • Not be inventory-tracked.
  • Have dynamic pricing set from the quote's premium at the time of sale.
  • Store the quoteId as line item metadata (e.g., cart line item properties or custom attributes).
  • Display the Extend icon as its product image.

Cart / Order Summary Display When shipping protection has been added, show it in the order summary either as:

  • An additional line item with the product name, Extend icon, and price.
  • An additional charge below the subtotal (similar to shipping & handling).
⚠️

Branding requirement:

The display name must include "Extend" for regulatory compliance (e.g., "Extend Shipping Protection" or "Shipping Protection by Extend"). Include the Extend logo/icon and a link to plan details and terms.


Putting It Together

Both Product Protection and Shipping Protection follow a shared integration pattern. The table below highlights the key differences:

Product ProtectionShipping Protection
Pricing scopePer-productPer-cart / per-order
Offer endpointPOST /offers or GET /offersPOST /shipping-offers/quotes + GET /shipping-offers/config
Key identifierplanId (from offers[].plans.adh[].id)quoteId (from quote response id)
Cart representationOne warranty SKU per covered productOne shipping protection SKU per order
Recommended placementsPDP, Add-to-Cart modal, Cart, Order ConfirmationCart / Checkout (alongside shipping method)
Marketing content sourceoffers[].marketing object/shipping-offers/config/marketing endpoint
Order reportingOrders / Orders Upsert with planId per line itemOrders / Orders Upsert with quoteId on SP line item
Contract creationExtend creates a contract per product coveredExtend creates a contract per order/shipment
Refund eligibilityPer contract termsBefore first shipment only

The shared pattern:

Fetch Offers → Add to Cart → Orders / Orders Upsert → Contracts

For stores offering both Product Protection and Shipping Protection, you will integrate with both sets of endpoints. The order you report to Extend via the Orders API can include line items for both product protection plans and the shipping protection quote in a single API call.

📘

Next steps:

Once offers are live, use the Orders API to report sales