---
title: Implementing custom shipping carrier providers
related:
  - https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/example-creating-a-shipping-carrier-provider.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores.md
  - https://docs.kentico.com/13/custom-development/customizing-providers.md
  - https://docs.kentico.com/13/custom-development/creating-custom-modules.md
  - https://docs.kentico.com/13/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md
  - https://docs.kentico.com/13/custom-development/creating-custom-modules/creating-installation-packages-for-modules/example-creating-a-packageable-module.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

To create [shipping options](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md) not supported by Xperience by default, implement a custom shipping carrier provider. Shipping carrier providers are code packages that define [shipping carriers](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md), which you can add to your Xperience instance. The shipping carriers then enable creation of new shipping options.

Shipping carrier providers can either use offline calculation of the shipping costs (for example, shipping based on weight, [the shipping address country](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/example-creating-a-shipping-carrier-provider.md), date, etc.) or online cost calculation, which requires communication with other systems, typically via APIs of shipping companies (for example, FedEx, USPS, Australia Post). Carrier providers of this type can then provide a real-time shipping costs calculation or shipping option availability check. You can also combine both approaches to achieve your desired result.

## Relationship between carrier providers and shipping options

When you add a shipping carrier provider to Xperience, you can create a new [shipping carrier](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md) in the administration interface. Shipping carriers contain services, which are types of shipping provided by the carrier. Administrators can then create [shipping options](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md) based on the carrier's services.

For example, you can create a custom provider for a FedEx carrier and two services – _International Priority shipping_ and _International Economy shipping_. Then administrators create shipping options based on the carrier's services. They can also create multiple options based on one service.

## Creating carrier providers

To implement a custom shipping carrier provider, you need to create a class that inherits from the **ICarrierProvider** interface. If you wish to allow configuration of the carrier in the administration interface, you also need to create a corresponding module.

1. [Create a custom module](https://docs.kentico.com/13/custom-development/creating-custom-modules.md) to represent your carrier.
2. (Optional) Define a configuration interface for your carrier (for example, with login credentials for communication with a shipping company's API). Open the **Modules** application and edit the module representing your carrier. On the **User interface** tab, [create a UI element](https://docs.kentico.com/13/custom-development/creating-custom-modules/manually-creating-the-interface-for-custom-modules.md) to be used as the configuration tab.

   - The UI element must be assigned to the carrier's module. Otherwise, it will not be included in installation packages.
   - If your carrier does not need any configuration, you do not need to create any UI element.
   - Each carrier can have only one configuration tab (UI element).

     > **Tip:** To calculate shipping costs, shipping companies usually require the address from which packages are sent. You can [create a text box](https://docs.kentico.com/13/custom-development/extending-the-administration-interface/developing-form-controls/reference-field-editor.md) on the configuration tab to allow administrators to set this address.
3. (Optional) As you did for the carrier, you can also create UI elements as configuration tabs for the carrier's services. Configuration tabs of services are then displayed while editing any shipping option based on the given service.
   - Every service can have one configuration tab.
4. (Optional) If you need to communicate with an API of a shipping company, you may need to add their API web references to your Xperience instance:

   1. Download a WSDL file from a website of the shipping company (for example, FedEx offers its WSDL files in their [Documentation and Downloads](https://www.fedex.com/us/developer/web-services/process.html) section).
   2. Right-click **References** in your carrier project in the Visual Studio Solution Explorer and click **Add Service Reference**.

      ![Location of the Add Service Reference button](https://docs.kentico.com/docsassets/13/implementing-custom-shipping-carrier-providers/add_service_reference.png "Location of the Add Service Reference button")
   3. Click **Advanced** in the **Add Service Reference** dialog.
   4. In the **Service Reference Settings** dialog, click **Add Web Reference**.
   5. Enter the path of your downloaded WSDL file, and click **Add Reference**.
      - Visual Studio then generates a new class according to the reference file automatically. You can use the API's methods when implementing the carrier provider, for example in the [GetPrice](#implementingcustomshippingcarrierproviders-getprice) and [CanDeliver](#implementingcustomshippingcarrierproviders-candeliver) methods.
5. Create a new class in your module project in Visual Studio (for example **MyCustomCarrier.cs**) that implements the **ICarrierProvider** interface.

   1. Implement the **CarrierProviderName** property.

      ```csharp

      string CarrierProviderName
      {
              get;
      }

      ```

      The property returns the name of the carrier. The name is displayed in the administration interface when working with carriers or shipping options.
   2. Implement the **GetServices** method.

      ```csharp

      List<KeyValuePair<string, string>> GetServices()

      ```

      The method returns a list of code names (the first element in the list) and display names (the second element in the list) of the carrier's services. The code names serve as identifiers in code and macros. Display names are shown in the administration interface when working with shipping options.

      ![List of services](https://docs.kentico.com/docsassets/13/implementing-custom-shipping-carrier-providers/list_of_carrier_services.png "List of services")

      > **Tip:** If you have a multilingual site, create [resource strings](https://docs.kentico.com/13/multilingual-websites/setting-up-a-multilingual-user-interface/working-with-resource-strings.md) to store the display names of your services.

      ```csharp title="Example"

      // Returns 2-day, priority and standard overnight FedEx shipping services
      public List<KeyValuePair<string, string>> GetServices()
      {
            SortedDictionary<string, string> services = new SortedDictionary<string, string>
            {
                  {"PRIORITY_OVERNIGHT", "{$com.fedexcarrierprovider.priorityovernight$}"},
                  {"STANDARD_OVERNIGHT", "{$com.fedexcarrierprovider.standardovernight$}"},
                  {"FEDEX_2_DAY", "{$com.fedexcarrierprovider.2day$}"}
            };

            return services.ToList();
      }

      ```
   3. &#x20;Implement the **GetPrice** method.

      ```csharp

      decimal GetPrice(Delivery delivery, string currencyCode)

      ```

      The method calculates shipping costs of the specified delivery and then returns the total shipping cost in the specified currency.

      **Parameters of GetPrice – the Delivery class**

      The _Delivery_ class represents a set of items that the store ships using a shipping option. The class contains the following properties:

      - **IEnumberable Items** – the shipped items. Only products and product options of the _Products_ type are present.
      - **DateTime ShippingDate** – the date when the store passed the package to the shipping company
      - **decimal Weight** – total weight of the shipped package in the unit specified in the _ECommerceSettings.MassUnit()_ setting
      - **ShippingOptionInfo ShippingOption** – the shipping option used for the delivery
      - **AddressInfo DeliveryAddress** – the address where the package is delivered
      - **IDataContainer CustomData** – you can use this property for custom data

      > **Info:** When communicating with the API of a shipping company that supports a different [currency](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md) than the one used by the order, you need to perform currency conversions.
      >
      > You can use [exchange rates](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies/configuring-exchange-rates.md) entered in the **Store configuration** application by using the **CurrencyConverter.Convert(decimal amount, string inCurrencyCode, string toCurrencyCode, int siteID)** method, where:
      >
      > - **decimal amount** – sets the price in the original currency
      > - **string inCurrencyCode** – sets the code of the original currency
      > - **string toCurrenceCode** – sets the code of the currency to which the value is converted
      > - **int siteID** – the ID of the site whose exchange rates and currency options are used
      >
      > ```csharp title="Example"
      >
      > CurrencyConverter.Convert(shippingPrice, "USD", currencyCode, delivery.ShippingOption.ShippingOptionSiteID);
      >
      > ```
   4. &#x20;Implement the **CanDeliver** method.

      ```csharp

      bool CanDeliver(Delivery delivery)

      ```

      The method checks if the shipping option (specified in the _Delivery_ parameter) is available for shipping. See the information about the [GetPricemethod](#implementingcustomshippingcarrierproviders-getprice) to learn about the available parameters.

      > **Tip:** If you want your services to always be available, return true.
      >
      > ```csharp
      >
      > public bool CanDeliver(Delivery delivery)
      > {
      >       return true;
      > }
      >
      > ```
   5. &#x20;Implement the **GetConfigurationUIElementGUID** method.

      ```csharp

      Guid GetConfigurationUIElementGUID()

      ```

      The method returns the GUID of a UI element that the carrier uses as its configuration tab. The system then displays the configuration tab while editing a carrier on the **Shipping -> Carriers** tab in the **Store configuration** application.

      ![Location of another configuration tab](https://docs.kentico.com/docsassets/13/implementing-custom-shipping-carrier-providers/possibly_another_tab.png "Location of another configuration tab")

      If the carrier does not have a configuration tab, return _Guid.Empty_. To get the GUID of a UIElement, you can call the **UIElementInfoProvider.GetUIElementInfo(string resourceName, string elementName)** method available in the **CMS.Modules** namespace.

      ```csharp title="Example"

      using CMS.Modules;

      /// <summary>
      /// Returns the Guid of the carrier's configuration UI element, where moduleName is the code name
      /// of the module and elementName is the code name of the UIElement.
      /// </summary>
      public Guid GetConfigurationUIElementGUID()
      {
            UIElementInfo ui = UIElementInfoProvider.GetUIElementInfo(moduleName, elementName);
            return ui.ElementGUID;
      }

      ```
   6. Implement the **GetServiceConfigurationUIElementGUID** method.

      ```csharp

      Guid GetServiceConfigurationUIElementGUID(string serviceName)

      ```

      The method returns the GUID of a UI element that the service (specified with by code name in the _serviceName_ property) uses as its configuration tab. You can get the UI element GUID as in the [GetConfigurationUIElementGUID](#implementingcustomshippingcarrierproviders-getconfigurationuielementguid) method. The system then displays the configuration tab while editing a shipping option in the **Store configuration** application on the **Shipping -> Shipping options** tab. For example, the **Weight based shipping** service of the **Default carrier** has the **Shipping costs** tab. For services that do not have a configuration tab, return _Guid.Empty_.
6. Reference the module project in your live site (MVC) application to ensure the shopping carrier definition is accessible on the live site.

Now you have a shipping provider that enables you to [create carriers](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md) and then [shipping options](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md). If you create an [installation package](https://docs.kentico.com/13/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md) for the carrier's module, you can distribute the carrier to other Xperience instances.

> **Tip:** To see a sample carrier provider implementation that calculates shipping costs based on the country, see: [Example - Creating a shipping carrier provider](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/example-creating-a-shipping-carrier-provider.md)
