Integrating with Extend's Order API

This guide explains how to use the Extend Orders APIs effectively, with a focus on the recommended Orders Upsert endpoint, versioning, payload structure, and common pitfalls to avoid.

Overview

Extend's Orders Upsert API provides a single endpoint for creating and updating order records within Extend's system. All orders — whether they include Extend Product Protection, Category-based Protection (OBC), Shipping Protection, or no protection at all — can be sent through this API.

The endpoint uses the transactionId as a unique key: if an order with that transactionId already exists, it will be updated; otherwise, a new order is created. Each request should contain a full order snapshot (all customer details and line items), with only field-level changes to reflect updates.

Key Concepts

  • Full Snapshot Model: Every API call sends the complete, current state of the order. The API automatically detects additions and deletions by comparing the current request to the previous snapshot.
  • Idempotent by Design: Sending the same snapshot multiple times produces the same result. Use this to your advantage for retry logic.
  • Contract Creation on Fulfillment: Extend generates protection contracts (identified by contractId) only when line items are marked as fulfilled via the fulfilledQuantity field.

Authentication

Before making requests, authenticate via Extend's Authentication Guide to obtain your API credentials.


Category Orders (Recommended)

Best Practice: Category Orders are Extend's recommended and prescriptive approach for integrating protection plans. Category Orders allow a single contract to cover multiple products within the same product category, simplifying contract management, improving operational efficiency, and providing a better customer experience.

How Category Orders Work

Category Orders use a category_contract line item type that groups multiple products under a single protection contract based on their product category. Key characteristics:

  • One contract covers multiple products within the same category
  • Each product maintains its own coverage date and limit of liability (LoL), but all share the same contractId
  • Multiple category contracts per order are supported — for example, one contract for furniture items and another for electronics
  • Extend differentiates category contracts based on the plan.id provided in the request

Creating a Category Order

The following example creates an order with two furniture products (8 Dining Chairs and 1 Dining Extension Table) covered under a single 5-year furniture protection category contract.

Request:

PUT /orders

{
  "currency": "USD",
  "transactionId": "972868770",
  "transactionDate": 1748476800000,
  "storeId": "{{your-extend-store-id}}",
  "merchantCustomerId": "Customer1234",
  "poNumber": "PO4567",
  "saleOrigin": {
    "agentId": "Sam Smith",
    "channel": "store",
    "locationId": "Store number 17519",
    "storeId": "{{your-extend-store-id}}"
  },
  "customer": {
    "email": "[email protected]",
    "name": "Jane Smith",
    "phone": "1234567899",
    "billingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    },
    "shippingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    }
  },
  "lineItems": [
    {
      "lineItemTransactionId": "972868770_100_D736-01",
      "product": {
        "id": "D736-01",
        "title": "Dining Chair",
        "category": "Chairs",
        "listPrice": 15000,
        "purchasePrice": 10200,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-chair.jpg",
        "mfrWarranty": {
          "labor": 6,
          "parts": 6,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 8,
      "fulfilledQuantity": 0
    },
    {
      "lineItemTransactionId": "972868770_10_D984-02",
      "product": {
        "id": "D984-02",
        "title": "Dining Extension Table",
        "category": "Tables",
        "listPrice": 99999,
        "purchasePrice": 67999,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-table.jpg",
        "mfrWarranty": {
          "labor": 12,
          "parts": 12,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "type": "category_contract",
      "lineItemTransactionId": "972868770-A17-FURNID-5y",
      "quantity": 1,
      "fulfilledQuantity": 0,
      "plan": {
        "id": "A17-FURNID-5y",
        "purchaseDate": 1748476800000,
        "purchasePrice": 42999
      },
      "coveredProducts": [
        {
          "lineItemTransactionId": "972868770_100_D736-01",
          "productId": "D736-01",
          "quantity": 8
        },
        {
          "lineItemTransactionId": "972868770_10_D984-02",
          "productId": "D984-02",
          "quantity": 1
        }
      ]
    }
  ]
}

Key points about this payload:

  • fulfilledQuantity is 0 for all line items at order creation (no items have shipped yet)
  • The category_contract line item has quantity: 1 and fulfilledQuantity: 0
  • The coveredProducts array lists every product covered under this category contract, with their lineItemTransactionId, productId, and quantity
  • The plan.id value (A17-FURNID-5y) identifies the specific category protection plan
  • plan.purchasePrice is the total cost of the category protection plan (not the individual product prices)

Fulfilling a Category Order

When products in a category order are fulfilled (shipped/invoiced), update the fulfilledQuantity at both the product level and the category contract level.

Important: Once the first product within a category contract is fulfilled, set the category contract's fulfilledQuantity to 1. This triggers Extend to generate the contractId in the response. Omitting fulfilledQuantity at the category contract level may cause invoicing discrepancies.

Partial Fulfillment — Shipment 1 (Chairs shipped, Table pending)

PUT /orders

{
  "currency": "USD",
  "transactionId": "972868770",
  "transactionDate": 1748476800000,
  "storeId": "{{your-extend-store-id}}",
  "merchantCustomerId": "Customer1234",
  "poNumber": "PO4567",
  "saleOrigin": {
    "agentId": "Sam Smith",
    "channel": "store",
    "locationId": "Store number 17519",
    "storeId": "{{your-extend-store-id}}"
  },
  "customer": {
    "email": "[email protected]",
    "name": "Jane Smith",
    "phone": "1234567899",
    "billingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    },
    "shippingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    }
  },
  "lineItems": [
    {
      "lineItemTransactionId": "972868770_100_D736-01",
      "product": {
        "id": "D736-01",
        "title": "Dining Chair",
        "category": "Chairs",
        "listPrice": 15000,
        "purchasePrice": 10200,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-chair.jpg",
        "mfrWarranty": {
          "labor": 6,
          "parts": 6,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 8,
      "fulfilledQuantity": 8
    },
    {
      "lineItemTransactionId": "972868770_10_D984-02",
      "product": {
        "id": "D984-02",
        "title": "Dining Extension Table",
        "category": "Tables",
        "listPrice": 99999,
        "purchasePrice": 67999,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-table.jpg",
        "mfrWarranty": {
          "labor": 12,
          "parts": 12,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "type": "category_contract",
      "lineItemTransactionId": "972868770-A17-FURNID-5y",
      "quantity": 1,
      "fulfilledQuantity": 1,
      "plan": {
        "id": "A17-FURNID-5y",
        "purchaseDate": 1748476800000,
        "purchasePrice": 42999
      },
      "coveredProducts": [
        {
          "lineItemTransactionId": "972868770_100_D736-01",
          "productId": "D736-01",
          "quantity": 8
        },
        {
          "lineItemTransactionId": "972868770_10_D984-02",
          "productId": "D984-02",
          "quantity": 1
        }
      ]
    }
  ]
}

What changed:

  • Dining Chair fulfilledQuantity updated from 08 (all 8 chairs shipped)
  • Category contract fulfilledQuantity updated from 01 (first product fulfilled triggers contract creation)
  • Dining Extension Table fulfilledQuantity remains 0 (not yet shipped)
  • All other fields remain identical — always send the full snapshot

Full Fulfillment — Shipment 2 (Table now also shipped)

PUT /orders

{
  "currency": "USD",
  "transactionId": "972868770",
  "transactionDate": 1748476800000,
  "storeId": "{{your-extend-store-id}}",
  "merchantCustomerId": "Customer1234",
  "poNumber": "PO4567",
  "saleOrigin": {
    "agentId": "Sam Smith",
    "channel": "store",
    "locationId": "Store number 17519",
    "storeId": "{{your-extend-store-id}}"
  },
  "customer": {
    "email": "[email protected]",
    "name": "Jane Smith",
    "phone": "1234567899",
    "billingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    },
    "shippingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    }
  },
  "lineItems": [
    {
      "lineItemTransactionId": "972868770_100_D736-01",
      "product": {
        "id": "D736-01",
        "title": "Dining Chair",
        "category": "Chairs",
        "listPrice": 15000,
        "purchasePrice": 10200,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-chair.jpg",
        "mfrWarranty": {
          "labor": 6,
          "parts": 6,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 8,
      "fulfilledQuantity": 8
    },
    {
      "lineItemTransactionId": "972868770_10_D984-02",
      "product": {
        "id": "D984-02",
        "title": "Dining Extension Table",
        "category": "Tables",
        "listPrice": 99999,
        "purchasePrice": 67999,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-table.jpg",
        "mfrWarranty": {
          "labor": 12,
          "parts": 12,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 1,
      "fulfilledQuantity": 1
    },
    {
      "type": "category_contract",
      "lineItemTransactionId": "972868770-A17-FURNID-5y",
      "quantity": 1,
      "fulfilledQuantity": 1,
      "plan": {
        "id": "A17-FURNID-5y",
        "purchaseDate": 1748476800000,
        "purchasePrice": 42999
      },
      "coveredProducts": [
        {
          "lineItemTransactionId": "972868770_100_D736-01",
          "productId": "D736-01",
          "quantity": 8
        },
        {
          "lineItemTransactionId": "972868770_10_D984-02",
          "productId": "D984-02",
          "quantity": 1
        }
      ]
    }
  ]
}

What changed:

  • Dining Extension Table fulfilledQuantity updated from 01
  • Category contract fulfilledQuantity remains 1 (already triggered — it only needs to transition from 0 to 1 once)

Adding Products to a Category Order

To add a new product to an existing category order, include the new product line item and update the coveredProducts array on the category contract.

In this example, we add 4 Accent Chairs to the existing furniture category contract:

PUT /orders

{
  "currency": "USD",
  "transactionId": "972868770",
  "transactionDate": 1748476800000,
  "storeId": "{{your-extend-store-id}}",
  "merchantCustomerId": "Customer1234",
  "poNumber": "PO4567",
  "saleOrigin": {
    "agentId": "Sam Smith",
    "channel": "store",
    "locationId": "Store number 17519",
    "storeId": "{{your-extend-store-id}}"
  },
  "customer": {
    "email": "[email protected]",
    "name": "Jane Smith",
    "phone": "1234567899",
    "billingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    },
    "shippingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    }
  },
  "lineItems": [
    {
      "lineItemTransactionId": "972868770_100_D736-01",
      "product": {
        "id": "D736-01",
        "title": "Dining Chair",
        "category": "Chairs",
        "listPrice": 15000,
        "purchasePrice": 10200,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-chair.jpg",
        "mfrWarranty": {
          "labor": 6,
          "parts": 6,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 8,
      "fulfilledQuantity": 8
    },
    {
      "lineItemTransactionId": "972868770_10_D984-02",
      "product": {
        "id": "D984-02",
        "title": "Dining Extension Table",
        "category": "Tables",
        "listPrice": 99999,
        "purchasePrice": 67999,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-table.jpg",
        "mfrWarranty": {
          "labor": 12,
          "parts": 12,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 1,
      "fulfilledQuantity": 1
    },
    {
      "lineItemTransactionId": "972868770_100_D737-03",
      "product": {
        "id": "D737-03",
        "title": "Accent Chair",
        "category": "Chairs",
        "listPrice": 12000,
        "purchasePrice": 8500,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/accent-chair.jpg",
        "mfrWarranty": {
          "labor": 6,
          "parts": 6,
          "url": "https://www.brand.com/warranty"
        }
      },
      "quantity": 4,
      "fulfilledQuantity": 0
    },
    {
      "type": "category_contract",
      "lineItemTransactionId": "972868770-A17-FURNID-5y",
      "quantity": 1,
      "fulfilledQuantity": 1,
      "plan": {
        "id": "A17-FURNID-5y",
        "purchaseDate": 1748476800000,
        "purchasePrice": 42999
      },
      "coveredProducts": [
        {
          "lineItemTransactionId": "972868770_100_D736-01",
          "productId": "D736-01",
          "quantity": 8
        },
        {
          "lineItemTransactionId": "972868770_10_D984-02",
          "productId": "D984-02",
          "quantity": 1
        },
        {
          "lineItemTransactionId": "972868770_100_D737-03",
          "productId": "D737-03",
          "quantity": 4
        }
      ]
    }
  ]
}

What changed:

  • New Accent Chair line item added with unique lineItemTransactionId: 972868770_100_D737-03
  • coveredProducts array updated to include the new product
  • All existing line items remain in the payload (full snapshot)

Increasing Quantity on a Category Order

To increase the quantity of an existing product, update the quantity field on the product line item and the corresponding entry in coveredProducts.

Example: Increasing Dining Chairs from 8 to 10:

// Within lineItems array — product line item
{
  "lineItemTransactionId": "972868770_100_D736-01",
  "product": {
    "id": "D736-01",
    "title": "Dining Chair",
    "category": "Chairs",
    "listPrice": 15000,
    "purchasePrice": 10200,
    "purchaseDate": 1748476800000,
    "imageUrl": "https://example.com/dining-chair.jpg"
  },
  "quantity": 10,
  "fulfilledQuantity": 8
}

// Within the category_contract's coveredProducts array
{
  "lineItemTransactionId": "972868770_100_D736-01",
  "productId": "D736-01",
  "quantity": 10
}

What changed:

  • Product quantity updated from 810
  • coveredProducts entry quantity updated from 810
  • fulfilledQuantity remains at 8 (only 8 have shipped so far)

Refunding a Category Order

Full Order Refund

To refund all contracts associated with an order, set the order-level status to "refunded":

PUT /orders

{
  "currency": "USD",
  "transactionId": "972868770",
  "transactionDate": 1748476800000,
  "storeId": "{{your-extend-store-id}}",
  "status": "refunded",
  "merchantCustomerId": "Customer1234",
  "poNumber": "PO4567",
  "saleOrigin": {
    "agentId": "Sam Smith",
    "channel": "store",
    "locationId": "Store number 17519",
    "storeId": "{{your-extend-store-id}}"
  },
  "customer": {
    "email": "[email protected]",
    "name": "Jane Smith",
    "phone": "1234567899",
    "billingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    },
    "shippingAddress": {
      "address1": "535 Mission Street",
      "address2": "11th Floor",
      "city": "San Francisco",
      "countryCode": "US",
      "postalCode": "94526",
      "province": "CA"
    }
  },
  "lineItems": [
    {
      "lineItemTransactionId": "972868770_100_D736-01",
      "product": {
        "id": "D736-01",
        "title": "Dining Chair",
        "category": "Chairs",
        "listPrice": 15000,
        "purchasePrice": 10200,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-chair.jpg"
      },
      "quantity": 8,
      "fulfilledQuantity": 8
    },
    {
      "lineItemTransactionId": "972868770_10_D984-02",
      "product": {
        "id": "D984-02",
        "title": "Dining Extension Table",
        "category": "Tables",
        "listPrice": 99999,
        "purchasePrice": 67999,
        "purchaseDate": 1748476800000,
        "imageUrl": "https://example.com/dining-table.jpg"
      },
      "quantity": 1,
      "fulfilledQuantity": 1
    },
    {
      "type": "category_contract",
      "lineItemTransactionId": "972868770-A17-FURNID-5y",
      "quantity": 1,
      "fulfilledQuantity": 1,
      "plan": {
        "id": "A17-FURNID-5y",
        "purchaseDate": 1748476800000,
        "purchasePrice": 42999
      },
      "coveredProducts": [
        {
          "lineItemTransactionId": "972868770_100_D736-01",
          "productId": "D736-01",
          "quantity": 8
        },
        {
          "lineItemTransactionId": "972868770_10_D984-02",
          "productId": "D984-02",
          "quantity": 1
        }
      ]
    }
  ]
}

What changed:

  • Added "status": "refunded" at the order level
  • This refunds all associated contracts for the entire order

Partial Refund — Reducing Quantity

To partially refund a product, reduce its quantity and update the coveredProducts accordingly. The API will refund the difference.

Example: Reducing Dining Chairs from 8 to 6 (refunding 2 chairs):

// Product line item — reduced quantity
{
  "lineItemTransactionId": "972868770_100_D736-01",
  "product": {
    "id": "D736-01",
    "title": "Dining Chair",
    "category": "Chairs",
    "listPrice": 15000,
    "purchasePrice": 10200,
    "purchaseDate": 1748476800000,
    "imageUrl": "https://example.com/dining-chair.jpg"
  },
  "quantity": 6,
  "fulfilledQuantity": 6
}

// Updated coveredProducts in the category_contract
"coveredProducts": [
  {
    "lineItemTransactionId": "972868770_100_D736-01",
    "productId": "D736-01",
    "quantity": 6
  },
  {
    "lineItemTransactionId": "972868770_10_D984-02",
    "productId": "D984-02",
    "quantity": 1
  }
]

Partial Refund — Removing a Product

To fully remove a product from the order, omit it from the lineItems array and remove it from the coveredProducts array. The API will cancel or refund any existing contracts for the removed line items.

Alternative: Product Protection Orders

Product Protection is a simpler alternative to Category Orders that falls under the same product protection umbrella. While Category Orders (above) are the recommended approach, Product Protection may be appropriate when each product requires its own independent contract — for example, when products span unrelated categories or when your system cannot support the category_contract line item structure. The core API mechanics (full snapshots, transactionId, fulfilledQuantity) work identically; the difference is in how contracts are structured.

Product Protection orders cover individual products with their own dedicated protection plan. Each product-plan pairing creates a separate contract — unlike Category Orders, which group multiple products under a single contract.

Creating a Product Protection Order

The following example creates an order with two products, each paired with its own protection plan.

PUT /orders
 
{
  "currency": "USD",
  "transactionId": "PP-100200300",
  "storeId": "{{your-extend-store-id}}",
  "customer": {
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "5551234567",
    "billingAddress": {
      "address1": "100 Main Street",
      "city": "Austin",
      "countryCode": "US",
      "postalCode": "78701",
      "province": "TX"
    },
    "shippingAddress": {
      "address1": "100 Main Street",
      "city": "Austin",
      "countryCode": "US",
      "postalCode": "78701",
      "province": "TX"
    }
  },
  "total": 12198,
  "lineItems": [
    {
      "lineItemTransactionId": "PP-100200300_Line1",
      "product": {
        "id": "REF-2355",
        "title": "Standing Desk",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/standing-desk.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "lineItemTransactionId": "PP-100200300_Line2",
      "product": {
        "id": "REF-4580",
        "title": "Ergonomic Chair",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/ergonomic-chair.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    }
  ]
}

Key points:

  • Each product line item includes a plan object directly — no separate category_contract line item is needed
  • Each product-plan pair will generate its own contractId upon fulfillment
  • fulfilledQuantity starts at 0 for newly created orders

Fulfilling a Product Protection Order

Partial Fulfillment — Product 1 ships

Update fulfilledQuantity for the shipped product only:

PUT /orders
 
{
  "currency": "USD",
  "transactionId": "PP-100200300",
  "storeId": "{{your-extend-store-id}}",
  "customer": {
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "5551234567",
    "billingAddress": {
      "address1": "100 Main Street",
      "city": "Austin",
      "countryCode": "US",
      "postalCode": "78701",
      "province": "TX"
    },
    "shippingAddress": {
      "address1": "100 Main Street",
      "city": "Austin",
      "countryCode": "US",
      "postalCode": "78701",
      "province": "TX"
    }
  },
  "total": 12198,
  "lineItems": [
    {
      "lineItemTransactionId": "PP-100200300_Line1",
      "product": {
        "id": "REF-2355",
        "title": "Standing Desk",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/standing-desk.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 1
    },
    {
      "lineItemTransactionId": "PP-100200300_Line2",
      "product": {
        "id": "REF-4580",
        "title": "Ergonomic Chair",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/ergonomic-chair.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    }
  ]
}

What changed:

  • Standing Desk fulfilledQuantity updated from 01
  • The API response will include a contractId for the Standing Desk's protection plan
  • Ergonomic Chair remains at fulfilledQuantity: 0

Full Fulfillment — Product 2 ships

Send the same full snapshot with both products' fulfilledQuantity set to 1. The API response will now include contractId values for both products.

Refunding a Product Protection Order

Full Order Refund

Add "status": "refunded" at the order level (same pattern as Category Orders):

{
  "transactionId": "PP-100200300",
  "status": "refunded",
  // ... full order snapshot ...
}

Partial Refund — Single Line Item

To refund a specific product, either reduce its quantity or omit it entirely from the lineItems array. The API will refund or cancel the associated contract.


Shipping Protection Orders

Shipping Protection covers products against loss, damage, or theft during transit. It is added as a dedicated line item in the order with tracking and shipment details.

Creating an Order with Shipping Protection

The following example creates an order with two products, Product Protection plans for each, and a Shipping Protection line item covering both products.

PUT /orders

{
  "currency": "USD",
  "transactionId": "SP-500600700",
  "storeId": "{{your-extend-store-id}}",
  "customer": {
    "email": "[email protected]",
    "name": "Sarah Jones",
    "phone": "5559876543",
    "billingAddress": {
      "address1": "200 Oak Avenue",
      "city": "Round Rock",
      "countryCode": "US",
      "postalCode": "78664",
      "province": "TX"
    },
    "shippingAddress": {
      "address1": "200 Oak Avenue",
      "city": "Round Rock",
      "countryCode": "US",
      "postalCode": "78664",
      "province": "TX"
    }
  },
  "total": 20299,
  "lineItems": [
    {
      "lineItemTransactionId": "SP-500600700_Line1",
      "product": {
        "id": "REF-2355",
        "title": "Standing Desk",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/standing-desk.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "lineItemTransactionId": "SP-500600700_Line2",
      "product": {
        "id": "REF-4580",
        "title": "Ergonomic Chair",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/ergonomic-chair.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "lineItemTransactionId": "SP-500600700_ShippingProtection",
      "quoteId": "45005545-94c9-41a6-ade1-63514aa93f79",
      "shipmentInfo": []
    }
  ]
}

Key points about Shipping Protection:

  • The Shipping Protection line item uses a quoteId (obtained when the customer purchases Shipping Protection at checkout) — this identifies the specific coverage quote
  • shipmentInfo is an empty array at order creation because tracking details are typically not available yet
  • Shipment details are added in subsequent updates once products ship

Updating Shipment Tracking — Shipment 1

Once the first product ships, update the order to include tracking information in the shipmentInfo array:

PUT /orders

{
  "currency": "USD",
  "transactionId": "SP-500600700",
  "storeId": "{{your-extend-store-id}}",
  "customer": {
    "email": "[email protected]",
    "name": "Sarah Jones",
    "phone": "5559876543",
    "billingAddress": {
      "address1": "200 Oak Avenue",
      "city": "Round Rock",
      "countryCode": "US",
      "postalCode": "78664",
      "province": "TX"
    },
    "shippingAddress": {
      "address1": "200 Oak Avenue",
      "city": "Round Rock",
      "countryCode": "US",
      "postalCode": "78664",
      "province": "TX"
    }
  },
  "total": 20299,
  "lineItems": [
    {
      "lineItemTransactionId": "SP-500600700_Line1",
      "product": {
        "id": "REF-2355",
        "title": "Standing Desk",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/standing-desk.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 1
    },
    {
      "lineItemTransactionId": "SP-500600700_Line2",
      "product": {
        "id": "REF-4580",
        "title": "Ergonomic Chair",
        "category": "Furniture",
        "listPrice": 9400,
        "purchasePrice": 9400,
        "imageUrl": "https://example.com/ergonomic-chair.jpg"
      },
      "plan": {
        "id": "A1-FURIND-3y",
        "purchasePrice": 699
      },
      "quantity": 1,
      "fulfilledQuantity": 0
    },
    {
      "lineItemTransactionId": "SP-500600700_ShippingProtection",
      "quoteId": "45005545-94c9-41a6-ade1-63514aa93f79",
      "shipmentInfo": [
        {
          "productIds": ["REF-2355"],
          "shipmentDate": 1684427850000,
          "shippingProvider": "usps",
          "trackingId": "usps-9400111899223100001234",
          "trackingUrl": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223100001234",
          "source": {
            "address1": "500 Warehouse Blvd",
            "city": "Dallas",
            "countryCode": "US",
            "postalCode": "75201",
            "province": "TX"
          },
          "destination": {
            "address1": "200 Oak Avenue",
            "city": "Round Rock",
            "countryCode": "US",
            "postalCode": "78664",
            "province": "TX"
          }
        }
      ]
    }
  ]
}

What changed:

  • Standing Desk fulfilledQuantity updated from 01
  • shipmentInfo now contains a shipment record with tracking details for the Standing Desk
  • productIds references which product(s) are in this shipment
  • trackingId is used by the API to identify and manage individual shipments

Adding a Second Shipment

When the second product ships, add a new entry to the shipmentInfo array while retaining all previous shipment entries:

// Shipping Protection line item with both shipments
{
  "lineItemTransactionId": "SP-500600700_ShippingProtection",
  "quoteId": "45005545-94c9-41a6-ade1-63514aa93f79",
  "shipmentInfo": [
    {
      "productIds": ["REF-2355"],
      "shipmentDate": 1684427850000,
      "shippingProvider": "usps",
      "trackingId": "usps-9400111899223100001234",
      "trackingUrl": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223100001234",
      "source": {
        "address1": "500 Warehouse Blvd",
        "city": "Dallas",
        "countryCode": "US",
        "postalCode": "75201",
        "province": "TX"
      },
      "destination": {
        "address1": "200 Oak Avenue",
        "city": "Round Rock",
        "countryCode": "US",
        "postalCode": "78664",
        "province": "TX"
      }
    },
    {
      "productIds": ["REF-4580"],
      "shipmentDate": 1684514250000,
      "shippingProvider": "fedex",
      "trackingId": "fedex-794644790132",
      "trackingUrl": "https://www.fedex.com/fedextrack/?trknbr=794644790132",
      "source": {
        "address1": "500 Warehouse Blvd",
        "city": "Dallas",
        "countryCode": "US",
        "postalCode": "75201",
        "province": "TX"
      },
      "destination": {
        "address1": "200 Oak Avenue",
        "city": "Round Rock",
        "countryCode": "US",
        "postalCode": "78664",
        "province": "TX"
      }
    }
  ]
}

Critical: If you omit a previously sent shipment entry from the shipmentInfo array, the API will delete that shipment record. Always include all existing shipment entries when adding new ones.

Shipment Management via trackingId

The API uses trackingId within the shipmentInfo array to determine how to handle each shipment entry:

  • New trackingId: Creates a new shipment record
  • Existing trackingId with updated details: Updates the existing shipment record
  • Missing trackingId (previously sent but not included): Deletes that shipment record

Key Considerations

TransactionId and LineItemTransactionId

These two identifiers are the backbone of the Orders Upsert API:

  • transactionId (order level): Your order number. The API uses this to match incoming requests to existing orders.
  • lineItemTransactionId (line item level): Your order item number. Must be unique within an order.

Both are set at order creation and must not change in subsequent updates. If your OMS/ERP system does not generate stable identifiers by default, concatenate existing fields to create a unique, consistent value. Contact Extend if this is not possible in your system.

For products with multiple quantities, all units of the same SKU share the same lineItemTransactionId — use the quantity and fulfilledQuantity fields to track individual units.

Full Order Snapshot Requirement

Every API request must contain the complete, current state of the order — all customer details, all line items (including unchanged ones), and all shipment records.

The API determines changes by comparing the incoming snapshot to the previous one:

  • New lineItemTransactionId → line item is added
  • Missing lineItemTransactionId (previously present) → line item is cancelled/refunded
  • Changed field values on an existing line item → line item is updated

This means you cannot send "partial" updates with only the changed fields. The tradeoff is simplicity: you always send the same complete order payload, just with updated field values.

ContractId Response

When a line item's fulfilledQuantity transitions from 0 to a positive number, the API response includes a contractId for the associated protection plan. Store these values in your system for traceability, reconciliation, and claims management.

For Category Orders, the contractId is returned when the category_contract line item's fulfilledQuantity changes from 0 to 1 (triggered by the first product fulfillment within that contract).

For Product Protection, each product line item generates its own contractId independently upon fulfillment.

For Shipping Protection, a contractId is returned for the entire order's shipping protection coverage when applicable.

Combining Protection Types

Orders can include multiple protection types simultaneously. For example, you might have Category Orders for product protection combined with a Shipping Protection line item in the same order. The API handles each protection type independently based on the line item structure provided.


Field Reference

FieldLevelTypeDescription
transactionIdOrderStringUnique order identifier (order number). Used as the key for creates and updates.
storeIdOrderUUIDYour Extend store identifier.
currencyOrderStringCurrency code (e.g., "USD").
totalOrderNumberTotal order amount in cents.
statusOrderStringSet to "refunded" to refund the entire order.
transactionDateOrderTimestampOrder creation date in epoch milliseconds.
merchantCustomerIdOrderStringYour internal customer identifier.
poNumberOrderStringPurchase order number.
lineItemTransactionIdLine ItemStringUnique line item identifier within the order. Immutable after creation.
typeLine ItemString"category_contract" for category orders. Omit for standard product protection.
quantityLine ItemNumberTotal quantity ordered.
fulfilledQuantityLine ItemNumberQuantity fulfilled/shipped. Set to 0 at creation.
product.idProductStringYour product SKU/identifier.
product.categoryProductStringProduct category (e.g., "Furniture", "Electronics").
product.purchasePriceProductNumberProduct purchase price in cents. Drives limit of liability.
product.listPriceProductNumberProduct list/retail price in cents.
plan.idPlanStringExtend protection plan identifier.
plan.purchasePricePlanNumberProtection plan price in cents.
coveredProductsCategory ContractArrayProducts covered under this category contract. Required for type: "category_contract".
quoteIdShipping ProtectionUUIDQuote identifier for Shipping Protection.
shipmentInfoShipping ProtectionArrayArray of shipment tracking records.
shipmentInfo[].trackingIdShipmentStringTracking number. Used for shipment add/update/delete logic.
shipmentInfo[].shippingProviderShipmentStringCarrier name (e.g., "usps", "fedex").
shipmentInfo[].shipmentDateShipmentTimestampShip date in epoch milliseconds.
shipmentInfo[].productIdsShipmentArrayProduct IDs included in this shipment.

Best Practices Summary

  1. Use Category Orders as your default approach — they simplify contract management by covering multiple products under a single contract per category.
  2. Always send full order snapshots — never attempt partial updates. Include every line item and shipment record in every request.
  3. Treat transactionId and lineItemTransactionId as immutable — set them at creation and never change them.
  4. Track fulfilledQuantity at all levels — for Category Orders, update both the product lines and the category_contract line. Failure to do so may impact invoicing.
  5. Include all previous shipment entries — when adding new shipments to Shipping Protection, always retain prior entries or they will be deleted.
  6. Store contractId values — save the returned contract IDs for traceability, reconciliation, and claims reference.
  7. Use trackingId for shipment lifecycle management — the API uses this value to determine whether to add, update, or remove shipment records.
  8. Contact Extend for edge cases — if your system cannot maintain stable identifiers or has unique constraints, reach out for guidance.