Orders webhooks (API 2025-10): shipping_address and note_attributes intermittently missing when using Theme App Extensions

Hi Shopify Community :waving_hand:,

I’m facing multiple intermittent data consistency issues with Orders webhooks (API 2025-10) while building a hyperlocal / delivery-slot based Shopify app.

I’d like to confirm whether this behavior is expected and what the recommended best practice is.


Context

  • Shopify API version: 2025-10

  • Webhooks: orders/create

  • Storefront integration: Theme App Extension

  • Backend: Go

  • Checkout: Standard + COD

  • Region: India


Issue 1: shipping_address sometimes missing

For the same order, I observe:

  • Some webhooks include shipping_address

  • Some webhooks do not include shipping_address at all

  • This happens even when:

    • Products require shipping

    • Shipping address is visible in Shopify Admin

Example:

// Webhook A
"shipping_address": { ... }
{
   "stream":"stdout",
   "logtag":"F",
   "log":{
      "level":"INFO",
      "time":"2025-12-17T10:15:03.648324905Z",
      "message":[
         "Shopify's request payload:",
         {
            "admin_graphql_api_id":"gid://shopify/Order/8441147130162",
            "app_id":580111,
            "billing_address":{
               "address1":"AB Road",
               "address2":"Guna",
               "city":"Gwalior Division",
               "company":null,
               "country":"India",
               "country_code":"IN",
               "first_name":"sanyam",
               "last_name":"jain",
               "latitude":24.6627042,
               "longitude":77.3272795,
               "name":"sanyam jain",
               "phone":null,
               "province":"Madhya Pradesh",
               "province_code":"MP",
               "zip":"473001"
            },
            "browser_ip":"111.92.91.139",
            "buyer_accepts_marketing":false,
            "cancel_reason":null,
            "cancelled_at":null,
            "cart_token":"hWN6WyBpYjXzTKjY5C4KHPn8",
            "checkout_id":40290371797298,
            "checkout_token":"bc8ea0b65959703aee26ac8c371f0969",
            "client_details":{
               "accept_language":"en-IN",
               "browser_height":null,
               "browser_ip":"111.92.91.139",
               "browser_width":null,
               "session_hash":null,
               "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"
            },
            "confirmation_number":"FZTTNTUGP",
            "confirmed":true,
            "contact_email":"sanyam.jain@zopping.com",
            "countryIsoCode":"IN",
            "created_at":"2025-12-17T15:45:00+05:30",
            "currency":"INR",
            "financial_status":"pending",
            "fulfillment_status":null,
            "id":8441147130162,
            "name":"#1377",
            "order_number":1377,
            "order_status_url":"https://cz56gr-q0.myshopify.com/94141514034/orders/6df23e6b8e9b4203d0e58535acd57e7a/authenticate",
            "payment_gateway_names":[
               "Cash on Delivery (COD)"
            ],
            "presentment_currency":"INR",
            "processed_at":"2025-12-17T15:44:59+05:30",
            "source_name":"web",
            "subtotal_price":"2.00",
            "total_price":"2.36",
            "total_tax":"0.36",
            "total_weight":600,
            "updated_at":"2025-12-17T15:45:01+05:30",
            "line_items":[
               {
                  "id":18809155780914,
                  "product_id":9896932966706,
                  "variant_id":50221459177778,
                  "title":"Google Pixel 8a",
                  "variant_title":"Green",
                  "quantity":1,
                  "price":"1.00",
                  "grams":300,
                  "vendor":"My Store",
                  "taxable":true,
                  "tax_lines":[
                     {
                        "title":"IGST",
                        "price":"0.18",
                        "rate":0.18
                     }
                  ]
               },
               {
                  "id":18809155813682,
                  "product_id":9896932966706,
                  "variant_id":50163139051826,
                  "title":"Google Pixel 8a",
                  "variant_title":"Black",
                  "quantity":1,
                  "price":"1.00",
                  "grams":300,
                  "vendor":"My Store",
                  "taxable":true,
                  "tax_lines":[
                     {
                        "title":"IGST",
                        "price":"0.18",
                        "rate":0.18
                     }
                  ]
               }
            ],
            "shipping_address":{
               "address1":"AB Road",
               "address2":"Guna",
               "city":"Gwalior Division",
               "country":"India",
               "province":"Madhya Pradesh",
               "zip":"473001"
            }
         }
      ],
      "gofrVersion":"v1.40.0"
   },
   "time":"2025-12-17T10:15:03.648324905Z",
   "gofrVersion":"v1.40.0",
   "kubernetes":{
      "pod_id":"597e9669-9c6f-4892-ad7d-c1dab9794d2f",
      "host":"gke-products-cluster-zopping-stage-po-5e3fc193-s7ey",
      "docker_id":"1704e4e6d48013d6ac517e9de51634e32280044e8dc94fe5c2322996627390c6",
      "container_image":"us-central1-docker.pkg.dev/zs-products/zopping/partner-integrations:e0129feb9f26a8ba73eb76c4629684cd050f0fbf"
   }
}

// Webhook B
// ❌ shipping_address not present
{
  "stream": "stdout",
  "logtag": "F",
  "log": {
    "level": "INFO",
    "time": "2025-12-17T10:15:03.648324905Z",
    "message": [
      "Shopify's request payload:",
      {
        "admin_graphql_api_id": "gid://shopify/Order/8441147130162",
        "app_id": 580111,
        "billing_address": {
          "address1": "AB Road",
          "address2": "Guna",
          "city": "Gwalior Division",
          "company": null,
          "country": "India",
          "country_code": "IN",
          "first_name": "sanyam",
          "last_name": "jain",
          "latitude": 24.6627042,
          "longitude": 77.3272795,
          "name": "sanyam jain",
          "phone": null,
          "province": "Madhya Pradesh",
          "province_code": "MP",
          "zip": "473001"
        },
        "browser_ip": "111.92.91.139",
        "buyer_accepts_marketing": false,
        "cancel_reason": null,
        "cancelled_at": null,
        "cart_token": "hWN6WyBpYjXzTKjY5C4KHPn8",
        "checkout_id": 40290371797298,
        "checkout_token": "bc8ea0b65959703aee26ac8c371f0969",
        "client_details": {
          "accept_language": "en-IN",
          "browser_height": null,
          "browser_ip": "111.92.91.139",
          "browser_width": null,
          "session_hash": null,
          "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"
        },
        "closed_at": null,
        "confirmation_number": "FZTTNTUGP",
        "confirmed": true,
        "contact_email": "sanyam.jain@zopping.com",
        "countryIsoCode": "IN",
        "created_at": "2025-12-17T15:45:00+05:30",
        "currency": "INR",
        "current_shipping_price_set": {
          "presentment_money": {
            "amount": "0.00",
            "currency_code": "INR"
          },
          "shop_money": {
            "amount": "0.00",
            "currency_code": "INR"
          }
        },
        "current_subtotal_price": "2.00",
        "current_subtotal_price_set": {
          "presentment_money": {
            "amount": "2.00",
            "currency_code": "INR"
          },
          "shop_money": {
            "amount": "2.00",
            "currency_code": "INR"
          }
        },
        "current_total_additional_fees_set": null,
        "current_total_discounts": "0.00",
        "current_total_discounts_set": {
          "presentment_money": {
            "amount": "0.00",
            "currency_code": "INR"
          },
          "shop_money": {
            "amount": "0.00",
            "currency_code": "INR"
          }
        },
        "current_total_duties_set": null,
        "current_total_price": "2.36",
        "current_total_price_set": {
          "presentment_money": {
            "amount": "2.36",
            "currency_code": "INR"
          },
          "shop_money": {
            "amount": "2.36",
            "currency_code": "INR"
          }
        },
        "current_total_tax": "0.36",
        "current_total_tax_set": {
          "presentment_money": {
            "amount": "0.36",
            "currency_code": "INR"
          },
          "shop_money": {
            "amount": "0.36",
            "currency_code": "INR"
          }
        },
        "customer": {
          "admin_graphql_api_id": "gid://shopify/Customer/10114126053682",
          "created_at": "2025-11-27T12:54:25+05:30",
          "currency": "INR",
          "default_address": {
            "address1": "AB Road",
            "address2": "Guna",
            "city": "Gwalior Division",
            "company": null,
            "country": "India",
            "country_code": "IN",
            "country_name": "India",
            "customer_id": 10114126053682,
            "default": true,
            "first_name": "sanyam",
            "id": 11614119526706,
            "last_name": "jain",
            "name": "sanyam jain",
            "phone": null,
            "province": "Madhya Pradesh",
            "province_code": "MP",
            "zip": "473001"
          },
          "email": "sanyam.jain@zopping.com",
          "first_name": "sanyam",
          "id": 10114126053682,
          "last_name": "jain",
          "multipass_identifier": null,
          "note": null,
          "phone": "+917976603448",
          "state": "enabled",
          "tax_exempt": false,
          "tax_exemptions": [],
          "updated_at": "2025-12-17T15:45:01+05:30",
          "verified_email": false
        },
        "customer_locale": "en-IN",
        "defaultStoreId": "",
        "developer": "null",
        "device_id": null,
        "discount_applications": [],
        "discount_codes": [],
        "duties_included": false,
        "email": "sanyam.jain@zopping.com",
        "estimated_taxes": false,
        "financial_status": "pending",
        "fulfillment_status": null,
        "fulfillments": [],
        "id": 8441147130162,
        "landing_site": "/cart",
        "landing_site_ref": null,
        "line_item_groups": [],
        "line_items": [
          {
            "admin_graphql_api_id": "gid://shopify/LineItem/18809155780914",
            "current_quantity": 1,
            "fulfillable_quantity": 1,
            "fulfillment_service": "manual",
            "grams": 300,
            "id": 18809155780914,
            "name": "Google Pixel 8a - Green",
            "price": "1.00",
            "product_id": 9896932966706,
            "quantity": 1,
            "requires_shipping": true,
            "taxable": true,
            "title": "Google Pixel 8a",
            "variant_id": 50221459177778,
            "variant_title": "Green",
            "vendor": "My Store"
          },
          {
            "admin_graphql_api_id": "gid://shopify/LineItem/18809155813682",
            "current_quantity": 1,
            "fulfillable_quantity": 1,
            "fulfillment_service": "manual",
            "grams": 300,
            "id": 18809155813682,
            "name": "Google Pixel 8a - Black",
            "price": "1.00",
            "product_id": 9896932966706,
            "quantity": 1,
            "requires_shipping": true,
            "taxable": true,
            "title": "Google Pixel 8a",
            "variant_id": 50163139051826,
            "variant_title": "Black",
            "vendor": "My Store"
          }
        ],
        "order_number": 1377,
        "source_name": "web",
        "subtotal_price": "2.00",
        "taxes_included": false,
        "total_price": "2.36",
        "total_tax": "0.36",
        "total_weight": 600,
        "updated_at": "2025-12-17T15:45:01+05:30"
      }
    ],
    "gofrVersion": "v1.40.0"
  },
  "time": "2025-12-17T10:15:03.648324905Z",
  "gofrVersion": "v1.40.0",
  "kubernetes": {
    "pod_id": "597e9669-9c6f-4892-ad7d-c1dab9794d2f",
    "host": "gke-products-cluster-zopping-stage-po-5e3fc193-s7ey",
    "docker_id": "1704e4e6d48013d6ac517e9de51634e32280044e8dc94fe5c2322996627390c6",
    "container_image": "us-central1-docker.pkg.dev/zs-products/zopping/partner-integrations:e0129feb9f26a8ba73eb76c4629684cd050f0fbf"
  }
}

This is causing problems for fulfillment and delivery logic.


Issue 2: note_attributes missing even though visible in Admin

Using a Theme App Extension, I attach additional delivery metadata to the order.

These fields always appear correctly in Shopify Admin → Order → Additional details:

preferredSlotId
preferredTime
storeId
latitude
longitude
preferredDate
Delivery Slot Type
Product IDs

However, in Orders webhooks, the note_attributes field is sometimes completely missing, even in orders/updated.

Example webhook payload (redacted):

{
  "id": 8441161580850,
  "billing_address": {
    "latitude": 24.6323648,
    "longitude": 77.3001762
  },
  "shipping_address": {
    "address1": "Kushmoda, Guna",
    "province": "Madhya Pradesh"
  }
  // ❌ note_attributes missing
}


Backend Expectation (current logic)

My backend assumes location data always comes from note_attributes.

func getLatLongAndLandMark(payload map[string]interface{}) (lat, long, landMark, state string, err error) {
    noteAttribute, ok := payload["note_attributes"].([]interface{})
    if !ok {
       return "", "", "", "", fmt.Errorf("invalid note attribute for lat long")
    }

    for i := range noteAttribute {
       data, _ := noteAttribute[i].(map[string]interface{})
       if data != nil {
          name, _ := data["name"].(string)

          if name == "latitude" {
             lat, _ = data["value"].(string)
          }

          if name == "longitude" {
             long, _ = data["value"].(string)
          }

          if name == "Customer Address Line 1" {
             landMark, _ = data["value"].(string)
          }

          if name == "Customer State" {
             state, _ = data["value"].(string)
          }
       }
    }

    return lat, long, landMark, state, err
}

When note_attributes or shipping_address is missing, webhook processing fails.


Observations

  • Shopify webhooks appear to be eventual & partial

  • shipping_address may be omitted

  • note_attributes may be omitted

  • Billing address often contains latitude / longitude

  • Theme App Extensions do not seem to guarantee attribute persistence in webhooks


Questions for Shopify / Community

  1. Is it expected behavior in API 2025-10 that:

    • shipping_address is sometimes omitted?

    • note_attributes is sometimes omitted, even when visible in Admin?

  2. Are Theme App Extensions officially non-guaranteed for persisting note_attributes into Orders webhooks?

  3. Is the recommended approach to:

    • Treat Orders webhooks as triggers only

    • Always refetch the order via Admin API for full data?

  4. For critical structured data like latitude / longitude / delivery slot:

    • Is a Checkout UI Extension the only guaranteed solution?

    • Or should apps update orders post-creation using the Admin API?


Current Understanding / Hypothesis

Shopify webhooks are eventual & partial and should not be treated as a source of truth.
Critical data like location should not rely solely on note_attributes coming from Theme App Extensions.

I’d appreciate confirmation or correction from Shopify staff or experienced partners.

Thanks in advance

Hi @sanyam_Jain,

Looking at the webhooks you shared, there is much more that just the shipping address that is different between the two webhook payloads.

I specifically noticed the following:

  • webhook A is missing the fields:

    • closed_at
    • all current_... fields, like current_shipping_price_set, current_subtotal_price, etc.
    • the full customer object
    • customer_locale
    • landing_site
    • landing_site_ref
    • discount_applications
    • discount_codes
    • duties_included
    • estimated_taxes
    • discount_applications
    • discount_codes
    • duties_included
    • estimated_taxes
    • taxes_included
  • webhook B is missing the fields:

    • name
    • order_status_url
    • payment_gateway_names
    • processed_at
    • shipping_address

These seem like they are completely different webhooks honestly, can you confirm the following questions:

  • Are these the same webhook topic, orders/create if not what are the topics
  • Are these webhooks being received by different apps?
  • Are these webhooks being subscribed in different ways? (ie. subscription via API call or toml file configuration)

If they are the same orders/create webhook, and are from the same app, and susbcribed in the same way, then this does seem like unexpected behaviour, and we will need to look into this in further detail.

To do so we will need you to reach out to our Shopify Support Team via the Shopify Help Center, and when you do reach out please make sure you have the following prepared so we can fully investigate.

  • Ensure you are logged into the Help Center from the Partner Account that the app belongs to, or a Staff member account on the store in question.
  • What is the exact Webhook Endpoint URL
  • What is the actual Webhook topic from both examples (orders/create or otherwise)
  • What is the Webhook Subscription ID (if subscribed via API call)
  • What is the relevant section of the app’s toml file (if subscribed via toml file)
  • What is the .myshopify.com address store this is occurring on
  • What is the exact order and timeframe when this occurred

Additionally, we do mention in our Shopify.dev documentation that Webhook delivery are not guaranteed and you should implement fallbacks to retrieve any critical data via the API directly.

Your app shouldn’t rely solely on receiving data from Shopify webhooks. Because webhook delivery isn’t always guaranteed, you should implement reconciliation jobs to periodically fetch data from Shopify.