Carrier service not called when attaching to shipping zone (Admin) – intermittent behavior

Hi everyone,

We have a carrier-calculated shipping app and are seeing inconsistent behaviour when merchants try to attach our carrier service via Admin → Shipping & delivery → Zones → Add rates → Carrier.

In some cases, Shopify shows our carrier services correctly. In other cases, the Admin UI shows an empty list and Shopify never calls our carrier callback endpoint at all (confirmed via logs).

Is this consistent with your experience?

  • Are there documented best practices for admin vs checkout carrier behavior?

  • Any known invalidation triggers we should account for?

Thanks in advance!

Below is the code related details

app.post(“/api/carrier-service/create”, async (_req, res) => {

try {

const carrier_service = new shopify.api.rest.CarrierService({

session: res.locals.shopify.session,

});

carrier_service.name = “Fast Courier”;

carrier_service.callback_url =

“https://shop.test.com.au/api/shipping-rates”;

carrier_service.service_discovery = true;

await carrier_service.save({

update: true,

});

res.status(200).send(carrier_service);

} catch (error) {

console.log(“carrier-create=”, error);

res.status(500).send(error);

}

});

Hi @suraj_rawat

The first thing I’d recommend is to migrate to using the GraphQL API - the REST API is legacy and may have inconsistent behavior. Following from that, you could be seeing this behaviour due to the carrier services not being associated with a location.

The Admin UI uses the availableCarrierServices query which returns carrier services and their associated shop locations. If a carrier service isn’t associated with the location configured in a shipping profile/zone, it won’t appear in the Admin dropdown.

You can verify this by running this GraphQL query:

query {
  availableCarrierServices {
    carrierService {
      id
      name
      active
      callbackUrl
      supportsServiceDiscovery
    }
    locations {
      id
      name
    }
  }
}

If your carrier service has an empty locations array for certain shops, that explains the intermittent behavior.

Hey Liam, Thanks for responding. As you said I ran the availableCarrierServices query and it correctly returns the locations. The carrier also appears in the Shopify admin dropdown. However, the callback URL is never being triggered—I’ve confirmed this by checking the server logs and no requests are coming in.

Result of the GraphiQL query

{
  "data": {
    "availableCarrierServices": [
      {
        "carrierService": {
          "id": "gid://shopify/DeliveryCarrierService/71941619891",
          "name": "Fast Courier",
          "active": true,
          "callbackUrl": null,
          "supportsServiceDiscovery": true
        },
        "locations": [
          {
            "id": "gid://shopify/Location/31663947821",
            "name": "Show Room"
          },
          {
            "id": "gid://shopify/Location/79449718963",
            "name": "Warehouse"
          },
          {
            "id": "gid://shopify/Location/79449751731",
            "name": "Main Store"
          },
          {
            "id": "gid://shopify/Location/79449784499",
            "name": "To Be Sorted"
          }
        ]
      },
      {
        "carrierService": {
          "id": "gid://shopify/DeliveryCarrierService/75620090035",
          "name": "Carrier Service",
          "active": true,
          "callbackUrl": null,
          "supportsServiceDiscovery": true
        },
        "locations": [
          {
            "id": "gid://shopify/Location/31663947821",
            "name": "Show Room"
          },
          {
            "id": "gid://shopify/Location/79449718963",
            "name": "Warehouse"
          },
          {
            "id": "gid://shopify/Location/79449751731",
            "name": "Main Store"
          },
          {
            "id": "gid://shopify/Location/79449784499",
            "name": "To Be Sorted"
          }
        ]
      },
      {
        "carrierService": {
          "id": "gid://shopify/DeliveryCarrierService/75620286643",
          "name": "australia_post_mypost_business",
          "active": true,
          "callbackUrl": null,
          "supportsServiceDiscovery": true
        },
        "locations": [
          {
            "id": "gid://shopify/Location/31663947821",
            "name": "Show Room"
          },
          {
            "id": "gid://shopify/Location/79449718963",
            "name": "Warehouse"
          },
          {
            "id": "gid://shopify/Location/79449751731",
            "name": "Main Store"
          },
          {
            "id": "gid://shopify/Location/79449784499",
            "name": "To Be Sorted"
          }
        ]
      },
      {
        "carrierService": {
          "id": "gid://shopify/DeliveryCarrierService/43051548717",
          "name": "sendle",
          "active": true,
          "callbackUrl": null,
          "supportsServiceDiscovery": true
        },
        "locations": [
          {
            "id": "gid://shopify/Location/31663947821",
            "name": "Show Room"
          },
          {
            "id": "gid://shopify/Location/79449718963",
            "name": "Warehouse"
          },
          {
            "id": "gid://shopify/Location/79449751731",
            "name": "Main Store"
          },
          {
            "id": "gid://shopify/Location/79449784499",
            "name": "To Be Sorted"
          }
        ]
      }
    ]
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 3,
      "actualQueryCost": 3,
      "throttleStatus": {
        "maximumAvailable": 2000,
        "currentlyAvailable": 1997,
        "restoreRate": 100
      }
    }
  }
}

@Liam-Shopify Did you get change to have a look into this?

Hi @suraj_rawat

I think the problem here is the "callbackUrl": null, that you’re seeing in the result of the GraphiQL query.

That’s why Shopify never hits your server, it simply has no URL to call. This likely stems from using the legacy REST API to create the carrier service, which can result in the callback URL not being properly persisted or being invalidated over time, especially in combination with service_discovery: true.

I’d recommend re-registering your carrier service using the GraphQL Admin API (carrierServiceCreate or carrierServiceUpdate mutation) and explicitly setting the callbackUrl.

After that, re-run the availableCarrierServices query to confirm the URL is no longer null. Also make sure your callback endpoint is publicly accessible, responds with valid shipping rate JSON, and returns within Shopify’s ~10 second timeout window.

Hi @Liam-Shopify I’ve updated the API to GraphQL and verified in the logs that the callback URL is being attched. I’ve attached a couple of screenshots showing that the app is connected, but no services are displayed.

Note: In the shipment rate API, I’ve added fallback rates in case no rates are returned.

store carrier-services== [
{
id: ‘gid://shopify/DeliveryCarrierService/71941619891’,
name: ‘Fast Courier’,
callbackUrl: ‘https://shop.fastcourier.com.au/api/shipping-rates’`,`
active: true,
supportsServiceDiscovery: true
},
{
id: ‘gid://shopify/DeliveryCarrierService/75620090035’,
name: ‘Carrier Service’,
callbackUrl: null,
active: true,
supportsServiceDiscovery: true
},
{
id: ‘gid://shopify/DeliveryCarrierService/76029886643’,
name: ‘Interparcel’,
callbackUrl: null,
active: true,
supportsServiceDiscovery: false
}
]


Hi @suraj_rawat

If the app was reinstalled or its access token was rotated, the carrier service record may have been recreated without the callback URL being set. Also the GraphQL carrierServiceCreate mutation allows you to omit the callback URL if you’re using service discovery, but Shopify still needs a URL to actually request rates at checkout time.

Can you update each carrier service with a valid callback URL using the GraphQL mutation:

mutation {
  carrierServiceUpdate(input: {
    id: "gid://shopify/DeliveryCarrierService/75620090035"
    callbackUrl: "https://their-app.example.com/api/shipping/rates"
  }) {
    carrierService {
      id
      callbackUrl
    }
    userErrors {
      field
      message
    }
  }
}

After setting the callback URL, the rate requests should start flowing to your server.

Hi @Liam-Shopify , The carrier service added by my app is Fast Courier. Please find the details below:

{
id: ‘gid://shopify/DeliveryCarrierService/71941619891’,name: ‘Fast Courier’, callbackUrl: ‘https://shop.fastcourier.com.au/api/shipping-rates’, active: true, supportsServiceDiscovery: true}