Carrier Service API Discounts

Hello,

We’ve identified what looks like a defect in the Shopify Carrier Service API when a cart spans multiple shipping profiles. When Shopify fans out the rate request — one POST per shipping profile — the same order_totals.discount_amount is sent in every request, even
when the cart-level discount only applies to items in a subset of those profiles.

Because each request only carries a subset of the cart’s items, the carrier service has no way to know how much of discount_amount actually applies to the items it’s being asked to rate. Trusting the field as-is causes the same discount to be counted once per profile
request, which inflates the discount applied to our landed-cost / duty-and-tax calculations downstream.

Reproduction

  • Test store: kubie-test.myshopify.com
  • Cart: 1 × Long sleeve t-shirt ($253.28, shipping profile A) + 1 × The 3p Fulfilled Snowboard ($3,324.71, shipping profile B)
  • Discount: a $664.94 line-item discount applied to one item only

The cart triggered two carrier service requests (one per shipping profile). Both carry the same order_totals despite having disjoint item lists:

order_totals: {
subtotal_price: 357799, // cart subtotal in cents = $3,577.99
total_price: 291305, // cart total in cents = $2,913.05
discount_amount: 66494 // $664.94
}

Profile A request — items:
[{
name: “Long sleeve t shirt”,
product_id: 7348730364001,
variant_id: 42368229408865,
quantity: 1,
price: 25328
}]

Profile B request — items:
[{
name: “The 3p Fulfilled Snowboard”,
sku: “sku-hosted-1”,
product_id: 7303261913185,
variant_id: 42170180403297,
quantity: 1,
price: 332471
}]

The full $664.94 discount appears in both requests despite only applying to one of the line items. Items themselves don’t carry a per-line total_discount in the payload (or it’s always 0 in the requests we’ve observed), so the carrier can’t reconstruct the scoped
discount from the items either.

Impact

For any carrier service performing landed-cost / duty-and-tax calculations on international orders, this leads to systematic over-discounting: each profile request can validly only apply the portion of discount_amount that belongs to its own items, but the current
payload provides no way to determine that portion. The carrier is forced to either (a) ignore discount_amount entirely and miss legitimate cart discounts, or (b) apply it as given and overcount when the cart spans profiles.

Suggested fix

Any one of the following would resolve this:

  1. Scope order_totals per request — each profile request carries the portion of subtotal_price / total_price / discount_amount that applies to that request’s items. This matches the way items is already scoped per profile.
  2. Populate per-item total_discount on each line item with the discount allocated to that line. The carrier can sum to get the scoped total.
  3. Omit order_totals from per-profile requests entirely, since the cart-level value is ambiguous when the request is profile-scoped.

Option 1 or 2 would be ideal — option 3 would at least make the ambiguity explicit.

Here are the request bodies directly from Shopify:

Request from profile 1

Request from profile 1 
{
  origin: {
    country: "US",
    postal_code: "84770",
    province: "UT",
    city: "St. George",
    name: null,
    address1: "975 South Tech Ridge Drive",
    address2: "",
    address3: null,
    latitude: 37.0903599,
    longitude: -113.591417,
    phone: "",
    fax: null,
    email: null,
    address_type: null,
    company_name: "Kubie Test",
  },
  destination: {
    country: "FR",
    postal_code: "56400",
    province: null,
    city: "Auray",
    name: "Test Fr",
    address1: "124 Rue Abbé Philippe le Gall",
    address2: null,
    address3: null,
    latitude: null,
    longitude: null,
    phone: null,
    fax: null,
    email: null,
    address_type: null,
    company_name: null,
  },
  items: [
    {
      name: "Long sleeve t shirt",
      sku: null,
      quantity: 1,
      grams: 1361,
      price: 25328,
      vendor: "Kubie Test",
      requires_shipping: true,
      taxable: true,
      fulfillment_service: "manual",
      properties: {
      },
      product_id: 7348730364001,
      variant_id: 42368229408865,
    },
  ],
  currency: "USD",
  locale: "en-NZ",
  order_totals: {
    subtotal_price: 357799,
    total_price: 291305,
    discount_amount: 66494,
  },
  customer: null,
}

Request form Profile 2
{
  origin: {
    country: "US",
    postal_code: "",
    province: "AL",
    city: "",
    name: null,
    address1: "",
    address2: "",
    address3: null,
    latitude: null,
    longitude: null,
    phone: "",
    fax: null,
    email: null,
    address_type: null,
    company_name: "Kubie Test",
  },
  destination: {
    country: "FR",
    postal_code: "56400",
    province: null,
    city: "Auray",
    name: "Test Fr",
    address1: "124 Rue Abbé Philippe le Gall",
    address2: null,
    address3: null,
    latitude: null,
    longitude: null,
    phone: null,
    fax: null,
    email: null,
    address_type: null,
    company_name: null,
  },
  items: [
    {
      name: "The 3p Fulfilled Snowboard",
      sku: "sku-hosted-1",
      quantity: 1,
      grams: 0,
      price: 332471,
      vendor: "Kubie Test",
      requires_shipping: true,
      taxable: true,
      fulfillment_service: "manual",
      properties: {
      },
      product_id: 7303261913185,
      variant_id: 42170180403297,
    },
  ],
  currency: "USD",
  locale: "en-NZ",
  order_totals: {
    subtotal_price: 357799,
    total_price: 291305,
    discount_amount: 66494,
  },
  customer: null,
}

Please let me know if there’s a more specific channel for Carrier Service API defects.