---
title: Implementing custom shipping carrier providers
related:
  - https://docs.kentico.com/k10/e-commerce-features/customizing-and-developing-your-store/shipping-related-customizing/implementing-custom-shipping-carrier-providers/example-creating-a-shipping-carrier-provider-with-costs-based-on-the-country.md
  - https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-shipping-options/configuring-shipping-carriers.md
  - https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-shipping-options.md
  - https://docs.kentico.com/k10/e-commerce-features/customizing-and-developing-your-store/shipping-related-customizing/example-custom-shipping-option-selection.md
  - https://docs.kentico.com/k10/e-commerce-features/configuring-your-store.md
  - https://docs.kentico.com/k10/custom-development/customizing-providers.md
  - https://docs.kentico.com/k10/custom-development/creating-custom-modules.md
  - https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md
  - https://docs.kentico.com/k10/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/k10/e-commerce-features/configuring-your-store/configuring-shipping-options.md) not supported by Kentico out of the box, create a shipping carrier provider. Shipping carrier providers are source code packages providing [shipping carriers](https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-shipping-options/configuring-shipping-carriers.md), which you can add to your Kentico. Shipping carriers then enable new shipping options in your Kentico instance.

You can create shipping carrier providers with an off-line cost calculation, which doesn't need to communicate with other systems (for example, shipping based on weight, [based on customer's country](https://docs.kentico.com/k10/e-commerce-features/customizing-and-developing-your-store/shipping-related-customizing/implementing-custom-shipping-carrier-providers/example-creating-a-shipping-carrier-provider-with-costs-based-on-the-country.md), based on date), or carrier providers with an on-line cost calculation, which communicate with other systems, typically with 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.

> **Tip:** You can[ create an installation package](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md) out of your carrier provider module and then [install the package](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules/installing-modules-from-installation-packages.md) on various instances of Kentico.

## Relationship between carrier providers and shipping options

In a more detailed view, when you add shipping carrier provider to Kentico, you can create new shipping carrier in the administration interface. Shipping carriers contain services, which are types of shipping of the carrier. Administrators can then create shipping options based on the services of the carrier.

For example, you can create a custom carrier provider with a FedEx carrier with two services – _International Priority shipping_ and _International Economy shipping_. Then, in the administration interface of Kentico, the system allows administrators to create shipping options based on services of your carrier. They can also create more options based on one service.

## Creating carrier providers

To create a custom shipping carrier, you must create a module with its user interface and then implement a class that inherits the **ICarrierProvider** interface.

1. [Create a custom module](https://docs.kentico.com/k10/custom-development/creating-custom-modules.md) and [a module project](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md) to represent your carrier.

   > **Tip:** See [an example](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules/example-creating-a-packageable-module.md) to get more integral view.
2. (Optional) In the **Modules** application, edit the module representing your carrier, and on the **User interface** tab, [create a UI element](https://docs.kentico.com/k10/custom-development/creating-custom-modules/manually-creating-the-interface-for-custom-modules.md) which will be then used as a configuration tab of your carrier (for example, with a login form for communication with an API of its shipping company).

   - You need to create the UI element in the same module. Otherwise, it will not be included in the installation package.
   - If your carrier does not need any configuration, you do not need to create any UI element.
   - Since every carrier can have only one configuration tab, create only one UI element for it.

     > **Tip:** To calculate shipping costs, shipping companies usually require an address of the place from where you send the bought items. You can [create a text box](https://docs.kentico.com/k10/custom-development/developing-form-controls/reference-field-editor.md) on the configuration tab for the address.
3. (Optional) As you did for the carrier, you can also create UI elements as configuration tabs for services of the carrier. 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 Kentico 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/k10/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 will then generate a new class according to the reference file automatically. You can then use its methods to implement the carrier provider, for example in the [GetPrice method](#implementingcustomshippingcarrierproviders-getprice) and the [CanDeliver method](#implementingcustomshippingcarrierproviders-candeliver).
5. Create a new class in your project in Visual Studio (for example **MyCustomCarrier.cs**) that implements the **ICarrierProvider** interface.

   1. Label the class with the following assembly attribute:

      ```csharp

      [assembly: RegisterCustomClass("MyCustomCarrier", typeof(MyCustomCarrier))]
      public class MyCustomCarrier : ICarrierProvider
      {
      }

      ```
   2. 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.
   3. 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 services of the carrier. You can use the code names in the code and in macros; the administration interface uses display names when working with shipping options.

      ![List of services](https://docs.kentico.com/docsassets/k10/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/k10/multilingual-websites/setting-up-a-multilingual-user-interface/working-with-resource-strings.md) for display names of your services.

      **Example:**

      ```csharp

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

            return mServices.ToList();
      }

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

      ```csharp

      decimal GetPrice(Delivery delivery, string currencyCode)

      ```

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

      **Parameters of GetPrice – the Delivery class**

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

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

   > **Info:** Remember, you have also to take care of [exchange rates](https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-currencies/configuring-exchange-rates.md) when it comes to communication with an API of a shipping company when [currency](https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-currencies.md) of a given order is not in the currency supported by carrier and the API of the shipping company.
   >
   > You can use exchange rates entered in the **Store configuration** application by using the **CurrencyConverter.Convert(decimal amount, string inCurrencyCode, string toCurrencyCode, int siteID)** method in the **CMS.Ecommerce** namespace, 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 result currency to which the _decimal amount_ is to be converted,
   > - **int siteID** – ID of the current site.**Example:**
   >
   > ```csharp
   >
   > CurrencyConverter.Convert(shippingPrice, "USD", currencyCode, delivery.ShippingOption.ShippingOptionSiteID);
   >
   > ```

   5. &#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 implementing theGetPricemethod](#implementingcustomshippingcarrierproviders-getprice) above to learn more about parameters.

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

      ```csharp

      Guid GetConfigurationUIElementGUID()

      ```

      The method returns GUID of an UI element that the carrier uses as its configuration tab (which you created in the step 2). 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/k10/implementing-custom-shipping-carrier-providers/possibly_another_tab.png "Location of another configuration tab")

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

      **Example:**

      ```csharp

      using CMS.Modules;

      /// <summary>
      /// Returns Guid of the configuration tab of the carrier 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;
      }

      ```
   7. Implement the **GetServiceConfigurationUIElementGUID** method.

      ```csharp

      Guid GetServiceConfigurationUIElementGUID(string serviceName)

      ```

      The method returns the GUID of a UI element that the service (specified with its code name in the _serviceName_ property) uses as its configuration tab (which you created in the step 3). You can determine the 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 any configuration tabs, return _Guid.Empty_.
6. [Create the module installation package](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md).

   > **Tip:** You can see the already mentioned [example](https://docs.kentico.com/k10/custom-development/creating-custom-modules/creating-installation-packages-for-modules/example-creating-a-packageable-module.md).

Now you have a shipping provider that enables you to [create carriers](https://docs.kentico.com/k10/e-commerce-features/configuring-your-store/configuring-shipping-options/configuring-shipping-carriers.md) and then shipping options based on your programmed methods. You also have an installation package of the module and you can install it on other Kentico instances.

> **Tip:** See an [example of shipping based on the country](https://docs.kentico.com/k10/e-commerce-features/customizing-and-developing-your-store/shipping-related-customizing/implementing-custom-shipping-carrier-providers/example-creating-a-shipping-carrier-provider-with-costs-based-on-the-country.md).
