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:
| Product | Endpoints | Downstream |
|---|---|---|
| Product Protection | POST /offers or GET /offers | Leads → Orders / Orders Upsert → Contracts |
| Shipping Protection | GET /shipping-offers/config, GET /shipping-offers/config/marketing, POST /shipping-offers/quotes | Orders / 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 amarketingobject with pre-configured messaging and imagery. Leveraging this content ensures brand-compliant, optimized offers without additional design work.
Product Protection Offers
How It Works
- 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.
- Add to cart — When the customer selects a plan, add a warranty SKU to the cart containing the
planId, price, and associated product information. - Report the sale — After checkout, send the order to Extend via the Orders or Orders Upsert API.
- 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
}
]
}'| Field | Type | Required | Description |
|---|---|---|---|
storeId | string | Yes | Your unique Extend store identifier. |
currency | string | Yes | ISO 4217 currency code (e.g., "USD"). |
locale | string | No | Locale for language and region (e.g., "en_US"). |
items | array | Yes | Array of products to get offers for. |
items[].category | string | Yes | Merchant-provided product category. |
items[].productId | string | Yes | Unique product identifier (SKU or reference ID). |
items[].purchasePrice | integer | Yes | Product price in cents (e.g., $999.99 → 99999). |
items[].quantity | integer | Yes | Quantity 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¤cy=USD' \
--header 'Accept: application/json;version=2022-02-01' \
--header 'X-Extend-Access-Token: YOUR_ACCESS_TOKEN'| Parameter | Type | Required | Description |
|---|---|---|---|
storeId | string | Yes | Your unique Extend store identifier. |
productId | string | Yes | Unique product identifier. |
category | string | Yes | Merchant-provided product category. |
purchasePrice | integer | Yes | Product price in cents. |
locale | string | No | Locale code (e.g., "en_US"). |
currency | string | No | ISO 4217 currency code. |
region | string | No | Region 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
| Path | Description |
|---|---|
offers[].plans.adh[] | Array of Accidental Damage from Handling (ADH) plans. |
offers[].plans.base[] | Array of base (non-ADH) plans. |
offers[].plans.recommended | Which plan type Extend recommends ("adh" or "base"). |
offers[].plans.adh[].id | The planId — include this in the cart and pass it to the Orders API. |
offers[].plans.adh[].price | Plan price in cents. |
offers[].plans.adh[].title | Display title for the plan. |
offers[].plans.adh[].url | Link to Extend-hosted plan details page. |
offers[].plans.adh[].offerPlanId | Reference ID for Extend analytics tracking. |
offers[].marketing | Pre-configured marketing content for each offer surface (PDP, modal, cart, etc.). |
surfaceVersion | Indicates 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 Key | Use Case |
|---|---|
productDetailsPageV2 | Product Detail Page (PDP) inline offer. |
offerTypeModalV2 | Pop-up modal offer (e.g., triggered on "Add to Cart"). |
offerTypeCTAV2 | Cart-level call-to-action banner. |
offerTypeCTA | Simple single-line CTA (e.g., "Add protection for $X"). |
learnMoreModal | "What's covered?" informational modal. |
planDetails | Full plan details page content (FAQs, rundown, fine print). |
orderConfirmationOfferV1 | Post-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: UsesurfaceVersionto 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:
- Fetch config — Call
/shipping-offers/configand optionally/shipping-offers/config/marketingto get offer display configuration and marketing content. - Get a quote — Call
/shipping-offers/quoteswith the cart contents to receive apremium(price) and aquoteId. - Add to cart — Represent the shipping protection as a single non-inventory SKU in the cart, priced at the quote's
premium. - Report the sale — Include the
quoteIdas 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'| Parameter | Type | Required | Description |
|---|---|---|---|
storeId | string | Yes | Your Extend store identifier. |
locale | string | No | Locale 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 a404. 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
}
]
}'| Field | Type | Required | Description |
|---|---|---|---|
storeId | string | Yes | Your Extend store identifier. |
currency | string | Yes | ISO 4217 currency code. |
items | array | Yes | Array of cart items. |
items[].referenceId | string | Yes | Product identifier (SKU, barcode, or database ID). |
items[].purchasePrice | integer | Yes | Product price in cents. |
items[].productName | string | No | Display name of the product. |
items[].quantity | integer | Yes | Quantity in the cart. |
items[].shippable | boolean | No | Whether the item is physically shipped. Non-shippable items (digital goods, services) are excluded. |
Response
{
"id": "d4f5a6b7-8c9d-0e1f-2a3b-4c5d6e7f8a9b",
"premium": 299,
"excluded_products": []
}| Field | Description |
|---|---|
id | The quote ID. Persist this value—it must be passed to the Orders API when reporting the sale. |
premium | The shipping protection price in cents to charge the customer. |
excluded_products | Products not eligible for shipping protection coverage. |
Important:If
premiumis0or noidis returned, do not display a shipping protection offer for this cart.
Carrying the quoteId into Orders
quoteId into OrdersWhen 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
premiumat the time of sale. - Store the
quoteIdas 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 Protection | Shipping Protection | |
|---|---|---|
| Pricing scope | Per-product | Per-cart / per-order |
| Offer endpoint | POST /offers or GET /offers | POST /shipping-offers/quotes + GET /shipping-offers/config |
| Key identifier | planId (from offers[].plans.adh[].id) | quoteId (from quote response id) |
| Cart representation | One warranty SKU per covered product | One shipping protection SKU per order |
| Recommended placements | PDP, Add-to-Cart modal, Cart, Order Confirmation | Cart / Checkout (alongside shipping method) |
| Marketing content source | offers[].marketing object | /shipping-offers/config/marketing endpoint |
| Order reporting | Orders / Orders Upsert with planId per line item | Orders / Orders Upsert with quoteId on SP line item |
| Contract creation | Extend creates a contract per product covered | Extend creates a contract per order/shipment |
| Refund eligibility | Per contract terms | Before 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
Updated about 7 hours ago