Develop custom solution

This section clarifies how to develop and integrate your own tailor-made shipping broker with our Partner Shipping solution.

You will have to create:

API

In the subsequent sections of this guide, we will use the term ‘Implementor’ to refer to you, the one integrating with our system.

Avarda will provide the client API, and also define the design and structure of both the requests and responses.

As the Implementor, you will be tasked with the development of an API. This API will receive and process requests from Avarda. It is crucial that your API adheres strictly to the design and structure set forth by Avarda to facilitate seamless interaction between the two components. As the Implementor, your primary responsibilities will include receiving request data, processing it in alignment with Avarda’s design, and returning the suitable response.

Overview

The Implementor API must include:

  • All required endpoints: The endpoints must adhere strictly to the names and contracts as detailed in this documentation.

  • A single base URL for all required endpoints: customization, such as versioning, is permitted for the base URL, provided it remains consistent across all required endpoints.

  • Bearer authorization: you will provide a secret for the customer that they will use in their Avarda checkout site configuration. Every request from the specific Avarda checkout site to your API will include this value in the authorization header, employing the bearer scheme.

View example of an implementation: https://partnershipping.azurewebsites.net/swagger (opens in a new tab)

create-session | required endpoint

This API endpoint is designated for initiating a new session, wherein a unique session ID must be generated by the Implementor. During this creation process, the Implementor should generate shipping options derived from the provided request data, which should be stored with some reference to the session. As the user has not yet interacted to select a shipping option, the response can include a pre-selected shipping option or remain void of any shipping selection.

Swagger example: https://partnershipping.azurewebsites.net/swagger/index.html#/Api/Api_CreateSession (opens in a new tab)

POST: {implementor_base_url}/create-session
Authorization: Bearer {access_token} // Implementor provides this token

Request body

{
  "purchaseId": "string",
  "locale": "sv-SE",
  "mode": 0, // B2C = 0, B2B = 1
  "checkoutSite": {
    "siteCode": "acmeSE",
    "countryCode": "SE",
    "currencyCode": "SEK"
  },
  "items": [
    {
      "description": "Random Item",
      "notes": "string",
      "amount": 399.0,
      "taxCode": "25",
      "taxAmount": 79.8,
      "quantity": 1,
      "shippingParameters": {
        "height": 1000,
        "length": 1000,
        "width": 100,
        "weight": 400,
        "attributes": ["string"]
      }
    }
  ],
  "shippingSettings": {
    "vouchers": ["string"],
    "attributes": ["string"]
  },
  "deliveryAddress": {
    "address1": "Address 12",
    "address2": "Acme Hotel",
    "street": "string",
    "houseNumber": "string",
    "zip": "12345",
    "city": "Stockholm",
    "type": "Private",
    "firstName": "Sven",
    "lastName": "Svensson",
    "country": "SE",
    "coordinates": {
      "lat": 0,
      "lng": 0
    }
  },
  "userInputs": {
    "email": "example@mail.com",
    "phoneCountryTwoLetterIso": "SE",
    "phone": "+46726417200"
  },
  "extraIdentifiers": {
    "orderReference": "string",
    "loyaltyNumber": "string",
    "productGroup": "string",
    "attachment": "string",
    "description": "string",
    "referenceName": "string"
  }
}
PropertyData TypeNecessityDescription
purchaseIdStringRequiredUnique identifier of the Avarda checkout purchase
(Avarda provides this Id)
localeStringRequiredLocale identifier / language tag (IETF BCP 47 standard).
Use this information to set language in widget.

E.g. sv-SE for Swedish or de-DE for German.
modeModeRequiredMode of the purchase (B2C/B2B)
checkoutSiteCheckoutSiteRequiredInformation about the Avarda checkout site
itemsItemRequiredCart items
shippingSettingsShippingSettingsOptionalAdditional shipping settings provided by partner
deliveryAddressDeliveryAddressRequiredDelivery address
userInputsUserInputsRequiredUser information
extraIdentifiersExtraIdentifiersOptionalPartner’s Avarda checkout session identifiers

Response body

{
  "id": "unique-implementor-session-id-123",
  "status": "ACTIVE",
  "expiresAt": "2023-07-13T11:30:54.8018377+00:00",
  "selectedShippingOption": {
    "shippingMethod": "pn-pp123",
    "deliveryType": "pickup",
    "carrier": "PostNord",
    "product": "Postal Parcel",
    "price": 15,
    "currency": "SEK"
  },
  "modules": "string"
}
PropertyData TypeNecessityDescription
idStringRequiredAn identifier of the shipping session on Implementors end.
Implementor generates this id upon creation.
statusStringRequiredThe status of the shipping session. This can be any string value since it isn’t used in any functionality on Avarda’s end.

E.g. “ACTIVE” or “COMPLETED”.
expiresAtDateTimeOffsetRequiredWhen the shipping session expires on Implementors end, expressed as date and time including time zone offset (ISO 8601 standard).

E.g. 2023-07-13T11:30:54.8018377+00:00
(yyyy-MM-ddTHH:mm:ss.ssssss±HH:mm)
selectedShippingOptionSelectedShippingOptionOptionalInformation about the selected shipping option
modulesStringOptionalAny extra information

update-session | required endpoint

This API endpoint is utilized to modify an existing session. The update operation includes the session ID (that Implementor generated during create-session), which is passed in both the route and the request body as “id”. As part of this update process, you are required to update the shipping options, taking into account the information present in the request body.

Swagger example: https://partnershipping.azurewebsites.net/swagger/index.html#/Api/Api_UpdateSession (opens in a new tab)

PUT: {implementor_base_url}/update-session/{id}
Authorization: Bearer {access_token} // Implementor provides this token

Request body

{
  "id": "unique-implementor-session-id-123",
  "purchaseId": "string",
  "locale": "sv-SE",
  "mode": 0, // B2C = 0, B2B = 1
  "checkoutSite": {
    "siteCode": "acmeSE",
    "countryCode": "SE",
    "currencyCode": "SEK"
  },
  "items": [
    {
      "description": "string",
      "notes": "string",
      "amount": 0,
      "taxCode": "string",
      "taxAmount": 0,
      "quantity": 0,
      "shippingParameters": {
        "height": 0,
        "length": 0,
        "width": 0,
        "weight": 0,
        "attributes": ["string"]
      }
    }
  ],
  "shippingSettings": {
    "vouchers": ["string"],
    "attributes": ["string"]
  },
  "deliveryAddress": {
    "address1": "string",
    "address2": "string",
    "street": "string",
    "houseNumber": "string",
    "zip": "string",
    "city": "string",
    "type": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "SE",
    "coordinates": {
      "lat": 0,
      "lng": 0
    }
  },
  "userInputs": {
    "email": "string",
    "phoneCountryTwoLetterIso": "SE",
    "phone": "string"
  },
  "extraIdentifiers": {
    "orderReference": "string",
    "loyaltyNumber": "string",
    "productGroup": "string",
    "attachment": "string",
    "description": "string",
    "referenceName": "string"
  }
}
PropertyData TypeNecessityDescription
idStringRequiredUnique identifier of the shipping session on Implementors end.
purchaseIdStringRequiredUnique identifier of the Avarda checkout purchase
(Avarda provides this Id)
localeStringRequiredLocale identifier / language tag (IETF BCP 47 standard).
Use this information to set language in widget.

E.g. sv-SE for Swedish or de-DE for German.
modeModeRequiredMode of the purchase (B2C/B2B)
checkoutSiteCheckoutSiteRequiredInformation about the Avarda checkout site
itemsItemRequiredCart items
shippingSettingsShippingSettingsOptionalAdditional shipping settings provided by partner
deliveryAddressDeliveryAddressRequiredDelivery address
userInputsUserInputsRequiredUser information
extraIdentifiersExtraIdentifiersOptionalPartner’s Avarda checkout session identifiers

Response body

{
  "id": "unique-implementor-session-id-123",
  "status": "ACTIVE",
  "expiresAt": "2023-07-13T11:30:54.8018377+00:00",
  "selectedShippingOption": {
    "shippingMethod": "string",
    "deliveryType": "string",
    "carrier": "string",
    "product": "string",
    "price": 0,
    "currency": "SEK"
  },
  "modules": "string"
}
PropertyData TypeNecessityDescription
idStringRequiredAn identifier of the shipping session on Implementors end.
statusStringRequiredThe status of the shipping session. This can be any string value since it isn’t used in any functionality on Avarda’s end.

E.g. “ACTIVE” or “COMPLETED”.
expiresAtDateTimeOffsetRequiredWhen the shipping session expires on Implementors end, expressed as date and time including time zone offset (ISO 8601 standard).

E.g. 2023-07-13T11:30:54.8018377+00:00
(yyyy-MM-ddTHH:mm:ss.ssssss±HH:mm)
selectedShippingOptionSelectedShippingOptionOptionalInformation about the selected shipping option
modulesStringOptionalAny extra information

complete-session | required endpoint

This API endpoint is designated for finalizing an existing session. The completion operation includes the session ID (that Implementor generated during create-session), which is passed in both the route and the request body as “id”.

As part of the completion procedure, a transport ID must be generated by the Implementor and saved within the session. After a successful completion, Avarda will not make any further updates to the shipping session.

Swagger example: https://partnershipping.azurewebsites.net/swagger/index.html#/Api/Api_CompleteSession (opens in a new tab)

PUT: {implementor_base_url}/complete-session/{id}
Authorization: Bearer {access_token} // Implementor provides this token

Request body

{
  "id": "unique-implementor-session-id-123",
  "deliveryAddress": {
    "address1": "string",
    "address2": "string",
    "street": "string",
    "houseNumber": "string",
    "zip": "string",
    "city": "string",
    "type": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "SE",
    "coordinates": {
      "lat": 0,
      "lng": 0
    }
  },
  "userInputs": {
    "email": "string",
    "phoneCountryTwoLetterIso": "string",
    "phone": "string"
  }
}
PropertyData TypeNecessityDescription
idStringRequiredUnique identifier of the shipping session on Implementors end.
deliveryAddressDeliveryAddressRequiredDelivery address
userInputsUserInputsRequiredUser information

Response body

{
  "id": "unique-implementor-session-id-123",
  "status": "COMPLETED",
  "transportId": "unique-implementor-transport-id-123",
  "expiresAt": "2023-07-13T11:30:54.8018377+00:00",
  "selectedShippingOption": {
    "shippingMethod": "string",
    "deliveryType": "string",
    "carrier": "string",
    "product": "string",
    "price": 0,
    "currency": "SEK"
  },
  "modules": "string"
}
PropertyData TypeNecessityDescription
idStringRequiredAn identifier of the shipping session on Implementors end.
statusStringRequiredThe status of the shipping session. This can be any string value since it isn’t used in any functionality on Avarda’s end.

E.g. “COMPLETED”.
transportIdStringRequiredA unique identifier of a completed shipping session on Implementors end.
Implementor generates this id upon completion.
expiresAtDateTimeOffsetRequiredWhen the shipping session expires on Implementors end, expressed as date and time including time zone offset (ISO 8601 standard).

E.g. 2023-07-13T11:30:54.8018377+00:00
(yyyy-MM-ddTHH:mm:ss.ssssss±HH:mm)
selectedShippingOptionSelectedShippingOptionOptionalInformation about the selected shipping option
modulesStringOptionalAny extra information

get-session | required endpoint

This API endpoint is purposed for retrieving an existing session, encompassing both active and completed sessions. The get operation includes the session ID (that Implementor generated during create-session), which is passed in both the route and the request body as “id”.

Swagger example: https://partnershipping.azurewebsites.net/swagger/index.html#/Api/Api_GetSession (opens in a new tab)

GET: {implementor_base_url}/get-session/{id}
Authorization: Bearer {access_token} // Implementor provides this token

Request body

Empty

Response body

{
  "id": "unique-implementor-session-id-123",
  "status": "string",
  "transportId": "string",
  "expiresAt": "2023-07-13T11:30:54.8018377+00:00",
  "selectedShippingOption": {
    "shippingMethod": "string",
    "deliveryType": "string",
    "carrier": "string",
    "product": "string",
    "price": 0,
    "currency": "SEK"
  },
  "modules": "string"
}
PropertyData TypeNecessityDescription
idStringRequiredAn identifier of the shipping session on Implementors end.
statusStringRequiredThe status of the shipping session. This can be any string value since it isn’t used in any functionality on Avarda’s end.

E.g. “ACTIVE” or “COMPLETED”.
transportIdStringOptionalA unique identifier of a completed shipping session on Implementors end.
Leave empty for non-completed sessions.
expiresAtDateTimeOffsetRequiredWhen the shipping session expires on Implementors end, expressed as date and time including time zone offset (ISO 8601 standard).

E.g. 2023-07-13T11:30:54.8018377+00:00
(yyyy-MM-ddTHH:mm:ss.ssssss±HH:mm)
selectedShippingOptionSelectedShippingOptionOptionalInformation about the selected shipping option
modulesStringOptionalAny extra information

Object Reference

Mode

ValueDescription
0B2C
1B2B

DeliveryAddressType

ValueDescription
"Default"Delivery address type can not be changed. The Private type is used as default
"Private"Delivery address type is set on Private
"Company"Delivery address type is set on Company

Coordinates

PropertyData TypeNecessityDescription
latIntegerOptionalLatitude
lngIntegerOptionalLongitude

CheckoutSite

PropertyData TypeNecessityDescription
siteCodeStringRequiredIdentifier of the Avarda checkout site
countryCodeStringRequiredCountry of the Avarda checkout site (alpha-2 country code from the ISO 3166-1 standard)

E.g. SE or FI
currencyCodeStringRequiredCurrency of the Avarda checkout site (ISO 4217 standard).
Use this information to set currency for shipping items.

E.g. SEK or EUR

Item

PropertyData TypeNecessityDescription
descriptionStringRequiredItem name / 0-35 length
notesStringOptionalItem notes / 0-35 length
amountDecimalRequiredPrice of the product inclusive of tax
taxCodeStringOptionalTax code
taxAmountDecimalRequiredTax amount
quantityIntegerRequiredQuantity of the same product. If quantity is used, the amount and taxAmount parameter should be defined for a single item.
shippingParametersShippingParametersOptionalExtra detailed information about the item

ShippingParameters

PropertyData TypeNecessityDescription
heightIntegerOptionalHeight of the item in millimeters
lengthIntegerOptionalLength of the item in millimeters
widthIntegerOptionalWidth of the item in millimeters
weightIntegerOptionalWeight of the item in grams
attributesstring[]OptionalAttributes of the item, use case depends on Implementor.
These values are passed “as is” to your API.

ShippingSettings

PropertyData TypeNecessityDescription
vouchersstring[]OptionalVouchers, use case depends on your implementation.
These values are passed “as is” to your API.
attributesstring[]OptionalAttributes of the entire cart, use case depends on your implementation.
These values are passed “as is” to your API.

DeliveryAddress

PropertyData TypeNecessityDescription
address1StringOptionalAddress line 1.
Full address including street name and house number.
address2StringOptionalAddress line 2.
Extra address information, e.g. c/o
streetStringOptionalStreet name (currently not used)
houseNumberStringOptionalHouse number (currently not used)
zipStringRequiredZip code
cityStringOptionalCity
typeString (DeliveryAddressType)OptionalType of address (Private/Company).
firstNameStringOptionalFirst name
lastNameStringOptionalLast name
countryStringOptionalCountry for the delivery address (alpha-2 country code from the ISO 3166-1 standard)

E.g. SE or FI
Note that this can be different from the CheckoutSite country.
coordinatesCoordinatesOptionalCoordinates (currently not used)

UserInputs

PropertyData TypeNecessityDescription
emailStringOptionalCustomer’s email address
phoneCountryTwoLetterIsoStringOptionalCustomer’s phone number country code (alpha-2 country code from the ISO 3166-1 standard)

E.g. SE or FI
phoneStringOptionalCustomer’s phone number
(A plain phone number without country information)

ExtraIdentifiers

PropertyData TypeNecessityDescription
orderReferenceStringOptionalMerchant’s custom ID reference
loyaltyNumberStringOptionalCan be a number of a customer’s membership card.
productGroupStringOptionalDefined the product category.
attachmentStringOptionalRandom merchant data (some kind of serialized JSON for example)
descriptionStringOptionalAn optional description provided by merchant. May be multi-line and may contain whatever the merchant wants.
referenceNameStringOptionalMerchant custom value reference name

SelectedShippingOption

PropertyData TypeNecessityDescription
shippingMethodStringRequiredUnique identifier of the shipping product

E.g. “pn-pu”
deliveryTypeStringRequiredType of delivery

E.g. “pickup”, “instore”, “mailbox” or “delivery”
carrierStringRequiredCompany name of carrier (shipping company)

E.g. “PostNord” or “DHL”
productStringRequiredName of the shipping product
priceDecimalRequiredPrice of shipping product in given currency
currencyStringRequiredCurrency (ISO 4217 standard)
Use currency provided from CheckoutSite

Widget

Register an interface called avardaShipping globally available on window object. This interface defines a set of methods for interacting with a shipping module. It includes methods for initializing the module, suspending and resuming its operation, registering event listeners, and unmounting the module.

  • init: Initialize widget inside the provided HTMLElement. Use session_id for rendering a correct shipping session. Use any modules data previously provided from create-session response, CustomStyles object for styling of the widget and language for selecting the same language as in the Checkout Form.

    • It should be possible to call init even after it was previously called.
  • unmount: Remove the shipping module from the page.

    • Module should be removed from the page and only a new init call should again make it visible.
  • suspend: Based on actions in Checkout – have ability to suspend the module to prevent any interaction from the user in the browser.

  • resume: Opposite of suspend

  • on: Allows us to attach event listener on the avardaShipping object, with specific type

  • dispatchEvent: Required for dispatching events that will be handled by Checkout Form

  • setLanguage: Change language to selected language by the Checkout. Language string will contain ISO 639 – 2 letter language code of one of the supported languages of Checkout.

  • sessionHasUpdated: When the shipping session has updated (due to change in delivery address - country, zip, etc.) this function will be called, check the status of the shipping and trigger shipping_option_changed if necessary.

It is required that the interface implements EventTarget interface to allow attaching and removing EventListeners and dispatching Event or CustomEvent.

Expected type contract

declare global {
  interface Window {
    avardaShipping?: AvardaShippingApi;
  }
}
 
export type CustomStyles = {
  fontFamily: string[];
  label: { selectedColor: string; unselectedColor: string };
  radio: { selectedColor: string; unselectedColor: string };
  borderRadius: number;
  amountColor: string;
};
 
export type Config = {
  modules: object | null;
  styles: CustomStyles | null;
  language: string;
  locale: string;
}
 
export type AvardaShippingInitObject = {
  element : HTMLElement;
  session_id: string;
  config: Config;
}
 
export interface AvardaShippingApi {
  init: (initObject:AvardaShippingInitObject) => void;
  suspend: () => void;
  resume: () => void;
  on(
    type: string,
    listener: EventListenerOrEventListenerObject,
    options?: boolean | AddEventListenerOptions
  ): void;
  dispatchEvent(event:Event) => boolean;
  unmount: () => void;
  setLanguage: (language:string) => void;
  sessionHasUpdated: () => void;
};

Checkout application is using WebComponent and ShadowDOM additionally, we also use WebComponent and ShadowDOM for the shipping module to prevent any unintentional leaking of CSS etc. To achieve this, we create a custom WebComponent on our side with all necessary work around it – and provide an HTMLElement in the init function.

Events

After the module is loaded into the page, we will attach 2 event listeners to the AvardaShippingApi

window.avardaShipping?.on('loaded', () => {
  // Checkout3 handles the event
});
window.avardaShipping?.on('shipping_option_changed', () => {
  // Checkout3 handles the event
});