How to Integrate your Shipping Provider with Native eCommerce

Create an app that allows native store merchants to offer their own shipping solution.

This step-by-step guide is designed to get you started with the core concepts of Native eCommerce’s external shipping provider feature. You will learn how to create an App inside Duda that allows merchants to offer their own shipping solution.

Prequisites

To follow along you’ll need:

  • Access to the Sandbox Environment
  • App Store API Credentials
  • An app UUID
  • Access to Duda's Native eCommerce

If you don't have these, contact [email protected].

1. Set Up App

To learn how to set up your Duda app, see our Getting Started guide.

2. Create an Account

When users install your shipping provider app on their website, you need to create an account with a record containing all the settings, auth details, site_name , etc. that you will need to process shipping for a website.

3. Create Settings Page

You need to create a settings page that allows merchants to connect their app account to your shipping provider. You can also expose a user interface on this page if you have settings the merchant can configure directly in Duda.

4. Register Shipping Provider

Once the merchant has fully configured the information in their account and your app is ready to provide shipping rates for orders, you need to register your shipping provider on the merchant’s website using our Create Shipping Provider API endpoint.

curl --request POST \
     --url https://api-sandbox.duda.co/api/integrationhub/application/site/{site_name}/ecommerce/shipping-providers \
     --header 'accept: application/json' \
     --header 'authorization: Basic {app_credentials}' \
     --header 'content-type: application/json' \
     --header 'X-DUDA-ACCESS-TOKEN: {access_token}' \
     --data '
{
  "live_shipping_rates_url": "https://example.org/live",
  "test_shipping_rates_url": "https://example.org/test"
}
'

Our API will return a shipping provider object in its response, as shown in the example below. You need to persist the shipping provider ID in your app account settings record to use later (logging, uninstalling process, etc.).

{
	"id": "esp_12345"
	"live_shipping_rates_url": "https://example.org/live",
  "test_shipping_rates_url": "https://example.org/test"
}

5. Retrieve Shipping Rates

Next, you need to retrieve shipping rates when the customer is at the shipping step during checkout. The following image shows the lifecycle of how shipping rates are retrieved during the shipping step at checkout.

Each time a customer is at the shipping step in the checkout process, our servers will make a POST request to your live_shipping_rates_url or test_shipping_rates_url with the customer’s cart data in its body to retrieve the availaible shipping rates.

Your shipping provider needs to respond with an array of available shipping rates to the POST request we sent. Each shipping rate returned will be displayed in the cart and can be selected by the customer.

Following is an example POST payload we will send to your live_shipping_rates_url or test_shipping_rates_url.

{
  "id": "88b29784-1f7d-4ac8-9542-2b7da382b580",
  "mode": "TEST",
  "status": "IN_PROGRESS",
  "created": "2023-06-02T13:27:39.61Z",
  "modified": "2023-06-02T13:27:39.688Z",
  "currency": "USD",
  "language": "en",
  "ip_address": "174.89.185.27",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
  "metadata": {},
  "subtotal": "44.10",
  "total": "44.10",
  "billing_address": {
    "first_name": "John",
    "last_name": "Doe",
    "full_name": "John Doe",
    "name": "John Doe",
    "address_1": "123 main rd.",
    "address_2": "apt. 1",
    "city": "Montreal",
    "region": "QC",
    "country": "CA",
    "postal_code": "H0H 0H0",
    "sub_locality": null,
    "phone": "4504504500",
    "street_name": null,
    "street_number": null
  },
  "shipping_address": {
    "first_name": "John",
    "last_name": "Doe",
    "full_name": "John Doe",
    "name": "John Doe",
    "address_1": "123 main rd.",
    "address_2": "apt. 1",
    "city": "Montreal",
    "region": "QC",
    "country": "CA",
    "postal_code": "H0H 0H0",
    "sub_locality": null,
    "phone": "4504504500",
    "street_name": null,
    "street_number": null
  },
  "items": [
    {
      "id": "depSI7zx_gqiMjOJL:_",
      "name": "Sun Lotion",
      "image": "https://cdn.dwhitelabel.com/md/dmtmpl/b9dc5218-1afb-4dd1-be44-37ffaed83e18/dms3rep/multi/Sun_lotion.jpg",
      "options": [
        {
          "name": "Size",
          "value": "50ml"
        }
      ],
      "quantity": 1,
      "unit_price": "40.00",
      "unit_weight": null,
      "unit_dimensions": {
        "height": null,
        "width": null,
        "length": null
      },
      "total": "40.00",
      "combined_weight": 0
    }
  ],
  "discounts": [],
  "taxes": [
    {
      "name": "TPS",
      "amount": "4.10",
      "rate": 0.1025
    }
  ]
}

Following is an example response to create the shipping rates at checkout:

{
	"methods": [
		{
			"id": "free-shipping", // Unique id of your shipping rate. This id will be persisted on the cart, and the order if it's selected by the customer
			"name": "Free shipping", // Display name of the shipping rate
			"price": "0.00", // Price of the shipping rate
			"min_delivery_time": 3, // (optional + future use) to display a range for delivery with max_delivery_time
			"max_delivery_time": 21 // (optional) To display the delevery time
		},
	  {
			"id": "express-shipping",
			"name": "Express shipping",
			"price": "14.00",
		},
		{
			"id": "standard-shipping",
			"name": "Standard shipping",
			"price": "12.47",
			"max_delivery_time": 14
		}
	]
}

Shipping Rate Error Message

If you need to block and display an error message to the customer, you can respond with an error payload to this POST request. This can be useful if your shipping provider can’t ship to a specific location, an error occurred while retrieving your shipping rates on your end, etc. Note that the error message will only display if no other shipping rates from other providers are displayed.

Following is an example response to display an error message at the shipping step to the customer.

{
	"error": {
		"code": "generic-error-code",
		"message": "No shipping rates are available to the shipping address you entered. Please try another address."
	}
}

6. Remove Shipping Provider

If a merchant needs to remove your shipping provider, the app will need to remove its shipping provider registration from the specific website. When the merchant uninstalls the app, our servers will make a HTTP call to the uninstallation_endpoint specified in the app manifest.

The call to this endpoint needs to trigger the deletion of the shipping provider on the website.

curl --request DELETE \
     --url https://api-sandbox.duda.co/api/integrationhub/application/site/{site_name}/ecommerce/shipping-providers/{shipping_provider_id} \
     --header 'accept: application/json' \
     --header 'authorization: Basic {app_credentials}' \
     --header 'content-type: application/json' \
     --header 'X-DUDA-ACCESS-TOKEN: {access_token}'