Documentation
Important notice

This feature is currently in beta version. Integrate with this API only if recommended by Ingrid Support Team. ūüöß


Reach out to Ingrid Support Team here to learn more about this feature.

Delivery Checkout API

Overview

The main goal of this section is to get the overall feeling of the API and the data flows.

Overview

Note

This section shows the examples in form of HTTP requests. You can leverage Delivery Checkout API Swagger to generate a client complying to the API and get started with using our API quickly.

Delivery Checkout is responsible for maintaining life cycle of a session that has all the data needed by the shipping selector widget. When a user visits checkout page, makes any changes to cart contents, selects shipping options and completes a purchase, all the relevant data are stored in the session.

Every session contains delivery_groups field which provides information about currently selected delivery option for each delivery group. Each delivery group in delivery_groups contains all important information such as:

If you are not using split shipment feature, delivery_groups field will always contain only one delivery group.

delivery_groups field should be used in integration to get final result of the session. The example result looks as follows:

{
"session": {
"checkout_session_id": "VM1-abfe8b49dc2848938361aa2fe9f71b63",
"status": "ACTIVE",
"delivery_groups": [
{
"items": [
{
"sku": "keyboard-sku",
"site_external_id": "STORE-1"
},
{
"sku": "mouse-sku",
"site_external_id": "STORE-2"
}
],
"shipping": {
"shipping_method": "pnl-bua",
"delivery_type": "mailbox",
"delivery_time": {
"id": "vG5OJYuvleuJGg7eYtvy2w",
"expires": "2021-11-16T15:00:00+01:00",
"start": "2021-11-17T00:00:00+01:00",
"end": "2021-11-29T00:00:00+01:00"
},
"external_method_id": "PUA",
"warehouse": {
"address": {
"name": "Warehouse A",
"address_lines": ["Sveavägen 21"],
"city": "Stockholm",
"postal_code": "11134",
"country": "SE",
"coordinates": {
"lat": 59.33565,
"lng": 18.06088
}
}
}
},
"category": {
"id": "category-letter-se",
"name": "Brev AB 1"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2021-11-16T15:00:00+01:00",
"latest": "2021-11-16T15:00:00+01:00"
},
"customer_delivery_promise": {
"earliest": "2021-11-17T00:00:00+01:00",
"latest": "2021-11-29T00:00:00+01:00"
},
"carrier_delivery_promise": {
"earliest": "2021-11-17T00:00:00+01:00",
"latest": "2021-11-29T00:00:00+01:00"
}
}
}
],
"updated_at": "2021-11-15T14:12:17Z"
}
}

If you decide not to use the split shipment or marketplace setting, delivery_groups field will always contain a single delivery group. You can always change the decision later and no additional integration changes will be needed to get you going with usage of split shipment (apart from handling other delivery groups results in your integration).

Create Session

The session.create method is used to create a new session. It returns the newly created Session as well as an HTML_snippet that can be embedded in the checkout page. Session can be created with minimal set of properties - purchase_country, purchase_currency, locales and cart.

Generic Flow

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when creating a new session and rendering shipping selector for that session onto the checkout page.

sequenceDiagram participant C as Customer participant M as Merchant participant A as Delivery Checkout API C->>M: Load checkout page M->>A: Create new session A->>M: Return shipping selector html snippet and session state M->>C: Render shipping selector html snippet on the page
  1. Customer loads the checkout page.
  2. Merchant calls the session.create method.
  3. Delivery Checkout API returns a new Session and the html_snippet needed to render the shipping selector.
  4. Merchant renders html_snippet on the page.

A minimal set of fields required to create a session is purchase_country, purchase_currency, locales and cart. To learn more about supported languages and browsers, see the Supported browsers and languages section. You can pass the shipping date specification along the create session request in order to manipulate the shipping date of the cart or cart items. It can be used to handle split shipment scenario when shipping date is used as a group-split condition. A new session is returned along with an identifier and a token for authorization.

Example Calls

Request

POST /v1/delivery_checkout/session.create HTTP/1.1
Host: api.ingrid.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer base64-encoded-api-token

{
"purchase_country": "SE",
"purchase_currency": "SEK",
"locales": [
"sv-SE"
],
"search_address": {
"postal_code": "11239",
"country": "SE"
},
"cart": {
"cart_id": "unique_id",
"total_value": 129900,
"currency": "SEK",
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"quantity": 1,
"attributes": [
"shoes",
"indigo",
"class_one"
]
}
]
}
}

Response

HTTP/1.1 200 OK
Date: Fri, 29 Jul 2022 09:08:36 GMT
Content-Type: application/json
Content-Length: 311
Connection: close
Vary: Accept-Encoding
x-trace-id: S2022072909083456GPPBK7C0Y0P7DY

{
"session": {
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"status": "ACTIVE",
"updated_at": "2022-07-29T09:08:36Z",
"cart": {
"total_value": 129900,
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"attributes": [
"shoes",
"indigo",
"class_one"
],
"quantity": 1
}
],
"cart_id": "unique_id"
},
"delivery_groups": [
{
"items": [
{
"sku": "SKU12345"
}
],
"shipping": {
"delivery_type": "instore",
"carrier": "Ingrid",
"product": "Pickup in Store",
"supports": {
"search": true
},
"warehouse": {
"address": {
"name": "Ingrid Swedish Warehouse",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.320672,
"lng": 18.035503
}
}
},
"carrier_product_id": "ProffsmagasinetBOX"
},
"category": {
"id": "to-store-32e78a504919437fa8e191adc389aaaa",
"name": "To Store",
"presented_category_name": "Delivery To Store"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2022-07-29T16:00:00+02:00",
"latest": "2022-07-29T16:00:00+02:00"
},
"customer_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
},
"carrier_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
}
},
"addresses": {
"location": {
"external_id": "I1",
"name": "Ingrid HQ",
"address": {
"name": "Ingrid HQ",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.3207318,
"lng": 18.0335876
}
},
"distance": {
"walking": {
"value": 1780,
"duration": 21
},
"driving": {
"value": 3097,
"duration": 6
}
}
},
"search_address": {
"postal_code": "11239",
"country": "SE",
"coordinates": {
"lat": 59.33122199302237,
"lng": 18.030565761645196
}
}
}
}
]
},
"html_snippet": "<div id='ingrid'> ... </div>",
"token": "Y2xpZW50dHdvOjA4OWRlZGU2NGM2ZjQwMWViMDE0ODA4Njc0MWQ0MzY2"
}

Update Session

The session.update method can be used to update the cart contents or to apply shipping date changes or split to the cart items. You can update either cart, apply shipping date, split cart items or everything in one request.

Generic flow when customer changes shipping option

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when updating a session. In this scenario shipping selector is the master so there is no need to suspend it.

sequenceDiagram participant C as Customer participant SS as Shipping Selector participant CO as Checkout participant M as Merchant participant A as Delivery Checkout API C->>SS: Change the shipping option SS->>CO: Fire option changed JS event CO->>M: Do Ajax call to backend M->>A: Call /session.get A->>M: Return Session state M->>M: Update order with new shipping cost M->>CO: Return new shipping cost CO->>CO: Update total cost CO->>C: Show new total
  1. Customer changes shipping option.
  2. Merchant is notified via JS event subscription.
  3. Merchant makes the Ajax call to its backend.
  4. Merchant fetches Ingrid Session using session.get and extracts the shipping cost.
  5. Merchant updates its order data in the backend.
  6. Merchant completes Ajax call and returns updated shipping cost.
  7. Merchant updates total cart cost with newly updated shipping cost.

Generic flow when cart contents change

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when updating a session and checkout page is master. Suspend call is needed in this use case.

sequenceDiagram participant C as Customer participant SS as Shipping Selector participant CO as Checkout participant M as Merchant participant A as Delivery Checkout API C->>CO: Update cart CO->>SS: Suspend CO->>M: Ajax call to backend M->>A: Call /session.update A->>M: Return updated session state M->>M: Update order with updated shipping cost M->>CO: Return Ajax call CO->>CO: Update cart and totals CO->>SS: Resume shipping selector SS->>M: Refresh state A->>SS: Return updated state SS->>C: Display fresh shipping options
  1. Put shipping selector in suspend mode using the Javascript API.
  2. Call Merchant backend to make the change, for example remove item from the cart.
  3. Apply the update to the Session using the session.update call.
  4. Updated session is returned.
  5. Merchant update order with updated shipping cost.
  6. Complete the Ajax call in the checkout.
  7. Resume shipping selector using the Javascript API.
  8. Shipping selector will then refresh its state.

Example Calls

Request

POST /v1/delivery_checkout/session.update HTTP/1.1
Host: api.ingrid.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer base64-encoded-api-token

{
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"carts": {
"cart_id": "unique_id",
"total_value": 274800,
"currency": "SEK",
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"quantity": 1,
"price": 129900,
"attributes": [
"shoes",
"indigo",
"class_one"
]
},
{
"sku": "SKU65432",
"name": "Michigan Coat XL",
"quantity": 1,
"price": 144900,
"attributes": [
"tops",
"spring_campaign"
]
}
]
}
}

Response

HTTP/1.1 200 OK
Date: Fri, 29 Jul 2022 09:08:36 GMT
Content-Type: application/json
Content-Length: 375
Connection: close
Vary: Accept-Encoding
x-trace-id: S20220729090836F5MN50PWRT9DAQA0

{
"session": {
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"status": "ACTIVE",
"updated_at": "2022-07-29T09:08:36Z",
"cart": {
"total_value": 129900,
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"attributes": [
"shoes",
"indigo",
"class_one"
],
"quantity": 1
}
],
"cart_id": "unique_id"
},
"delivery_groups": [
{
"items": [
{
"sku": "SKU12345"
}
],
"shipping": {
"delivery_type": "instore",
"carrier": "Ingrid",
"product": "Pickup in Store",
"supports": {
"search": true
},
"warehouse": {
"address": {
"name": "Ingrid Swedish Warehouse",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.320672,
"lng": 18.035503
}
}
},
"carrier_product_id": "ProffsmagasinetBOX"
},
"category": {
"id": "to-store-32e78a504919437fa8e191adc389aaaa",
"name": "To Store",
"presented_category_name": "Delivery To Store"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2022-07-29T16:00:00+02:00",
"latest": "2022-07-29T16:00:00+02:00"
},
"customer_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
},
"carrier_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
}
},
"addresses": {
"location": {
"external_id": "I1",
"name": "Ingrid HQ",
"address": {
"name": "Ingrid HQ",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.3207318,
"lng": 18.0335876
}
},
"distance": {
"walking": {
"value": 1780,
"duration": 21
},
"driving": {
"value": 3097,
"duration": 6
}
}
},
"search_address": {
"postal_code": "11239",
"country": "SE",
"coordinates": {
"lat": 59.33122199302237,
"lng": 18.030565761645196
}
}
}
}
]
},
"html_snippet": "<div id=\"shipwallet-container\" style=\"min-height:350px\"> <style> #ingrid-loader { min-height: 350px; padding: 32px 12px 12px 12px; border: 1px solid #e6e6e6; border-radius: 6px; background-color: white; } ._ingrid-skeleton { background-color: #ededed; position: relative; overflow: hidden; -webkit-mask-image: -webkit-radial-gradient(white, black); } ._ingrid-skeleton::before { content: ''; background-image: linear-gradient(90deg, #ededed 0px, #f8f8f8 80px, #ededed 160px); animation: transform 1.8s ease-out infinite; transform-origin: 0 0; width: 100vw; height: 100%; left: -160px; position: absolute; display: block; } ._ingrid-skeleton-text { height: 10px; } ._ingrid-skeleton-shipping-indicator { height: 45px; width: 100%; } ._ingrid-skeleton-shipping-indicator-label { margin-bottom: 20px; width: 100px; } ._ingrid-skeleton-delivery-categories-wrapper { display: flex; flex-direction: column; width: 100%; padding-bottom: 9px; } ._ingrid-skeleton-shipping-option-first-row { display: flex; align-items: center; width: 100%; } ._ingrid-skeleton-checkbox { width: 20px; height: 20px; border-radius: 10px; margin-right: 8px; } ._ingrid-skeleton-flex-1 { flex: 1; } ._ingrid-skeleton-shipping-option-name { width: 60%; } ._ingrid-skeleton-price { width: 30px; margin-right: 12px; } ._ingrid-skeleton-shipping-option-second-row { display: flex; width: 100%; } ._ingrid-skeleton-delivery-description { width: 35%; } ._ingrid-skeleton-delivery-logo { width: 32px; height: 32px; border-radius: 50%; } ._ingrid-skeleton-delivery-categories-label { width: 200px; } ._ingrid-skeleton-delivery-category-wrapper { padding-bottom: 16px; } @keyframes transform { to { transform: translateX(120%); } } ._ingrid-skeleton-zipcode-label { width: 70px; margin-bottom: 12px; } ._ingrid-skeleton-zipcode-input { height: 50px; width: 100%; margin-bottom: 28px; } </style> <div id=\"ingrid-loader\"> <div style=\"width: 100%\"> <div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-zipcode-label\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-zipcode-input\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-shipping-indicator-label\" ></div> <div class=\"_ingrid-skeleton-delivery-categories-wrapper\"> <div class=\"_ingrid-skeleton-delivery-category-wrapper\"> <div class=\"_ingrid-skeleton-shipping-option-first-row\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-shipping-option-name\" ></div> </div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-price\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-delivery-logo\"></div> </div> <div class=\"_ingrid-skeleton-shipping-option-second-row\"> <div class=\"_ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-delivery-description\" ></div> </div> </div> </div> <div class=\"_ingrid-skeleton-delivery-category-wrapper\"> <div class=\"_ingrid-skeleton-shipping-option-first-row\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-shipping-option-name\" ></div> </div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-price\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-delivery-logo\"></div> </div> <div class=\"_ingrid-skeleton-shipping-option-second-row\"> <div class=\"_ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-delivery-description\" ></div> </div> </div> </div> <div class=\"_ingrid-skeleton-delivery-category-wrapper\"> <div class=\"_ingrid-skeleton-shipping-option-first-row\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-shipping-option-name\" ></div> </div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-price\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-delivery-logo\"></div> </div> <div class=\"_ingrid-skeleton-shipping-option-second-row\"> <div class=\"_ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-delivery-description\" ></div> </div> </div> </div> <div class=\"_ingrid-skeleton-shipping-option-first-row\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-shipping-option-name\" ></div> </div> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-price\"></div> <div class=\"_ingrid-skeleton _ingrid-skeleton-delivery-logo\"></div> </div> <div class=\"_ingrid-skeleton-shipping-option-second-row\"> <div class=\"_ingrid-skeleton-checkbox\"></div> <div class=\"_ingrid-skeleton-flex-1\"> <div class=\"_ingrid-skeleton _ingrid-skeleton-text _ingrid-skeleton-delivery-description\" ></div> </div> </div> </div> </div> </div> </div> <script> (function(window, instanceId, containerId, document) { window[instanceId] = window[instanceId] || function() { (window[instanceId].q = window[instanceId].q || []).push(arguments) }; var bootstrapURL = \"https://cdn-stage.ingrid.com/checkout-widget/5f7aad6/bootstrap.js\"; var bootstrapFallbackURL = \"\"; if (/MSIE|Trident/.test(window.navigator.userAgent)) { bootstrapURL = bootstrapFallbackURL; } window[instanceId].config = { container: document.getElementById(containerId), bootstrapURL: bootstrapURL, bootstrapFallbackURL: bootstrapFallbackURL, features: {\"hide_toc\":false,\"show_shipping_price_on_service_points_view\":true,\"show_carrier_icons\":true,\"new_search_address\":true,\"door_code\":false,\"show_map\":true,\"hide_street_on_address_fields\":true,\"disable_address_form\":false,\"show_city_on_address_fields\":false,\"display_upfront_address\":false,\"autocomplete_street\":false,\"display_location_type\":false,\"dont_require_street_on_address_fields\":false,\"show_state_on_address_fields\":false,\"show_delivered_by\":false,\"show_street_on_address_module\":false,\"show_city_on_address_module\":false,\"require_street_on_address_module\":false,\"enable_ingrid_logo\":true,\"enable_widget_border\":true,\"enable_transparent_background\":false,\"show_shipping_categories_before_address\":true,\"enable_accent_color_for_widget_elements\":false,\"dark_color_enabled\":true,\"show_slogan\":false,\"show_carrier_logos_in_shipping_categories_placeholder\":true,\"enable_free_shipping_indicator\":true,\"enable_free_shipping_indicator_category_name_message\":true,\"enable_free_shipping_indicator_carrier_logo\":false,\"enable_delivery_address_form\":false,\"show_privacy_policy\":false,\"show_region\":false,\"require_region\":false,\"shipping_categories_visible_when_folded_count\":0,\"enable_multiple_home_delivery_in_category\":false,\"display_currency_iso_code\":false,\"enable_postal_code_in_location_address\":false,\"enable_analytics\":false,\"show_currency_before_price\":false,\"show_cancel_button_on_modal\":false}, instanceId: instanceId, locale: \"sv-SE\", logging: \"https://c7a68a2a3cfe4024bf719e6485aa8751@sentry.io/141995\", status: \"\\u0001\", style: {}, session: \"VM2-678b4f25ac5f43748be23eff5a59b344\", token: \"Y2xpZW50dHdvOjA4OWRlZGU2NGM2ZjQwMWViMDE0ODA4Njc0MWQ0MzY2\", version: \"\", loaderId: \"ingrid-loader\" }; var container = document.getElementById(containerId); var bootstrapScript = document.createElement(\"script\"); bootstrapScript.async = true; bootstrapScript.src = bootstrapURL; bootstrapScript.className = \"ingrid-bootstrap-script\"; bootstrapScript.addEventListener(\"load\", function (e) { if (typeof _ingrid_initializeWidgetInstance === \"function\") { _ingrid_initializeWidgetInstance(instanceId); } }); container.appendChild(bootstrapScript); })(window, '_sw', 'shipwallet-container', document); </script> <noscript> Please <a href=\"https://enable-javascript.com\">enable JavaScript</a>. </noscript></div>"
}

Complete Session

The session.complete method is used to mark a session as complete. At this point, if the customer has not made a choice we will generate one for the customer based on the information in the customer field provided in the request.

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when completing a session when the customer checkout.

sequenceDiagram participant C as Customer participant M as Merchant participant A as Delivery Checkout API C->>M: Completes the order M->>A: Call /session.complete A->>M: Return completed session state M->>C: Redirects to confirmation page
  1. Customer completes the transaction.
  2. Merchant completes the session using session.complete method.
  3. Delivery Checkout API returns session in a completed state. The SelectedShippingOption and tos_id are also returned.
  4. Merchant redirects the customer to the confirmation page.

On session complete call a tos_id will be returned (or multiple tos_ids if there is more than one delivery group in the result). This id is important if you need to re-open a session as a completed session is "frozen" and cannot be modified. You can use tos_id to clone a completed session.

Example Calls

Request

POST /v1/delivery_checkout/session.complete HTTP/1.1
Host: api.ingrid.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer base64-encoded-api-token

{
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"customer": {
"email": "erik@ingrid.com",
"phone": "0709997711",
"address": {
"name": "Erik Johansson",
"address_lines": [
"Industrigatan 5"
],
"city": "Stockholm",
"postal_code": "11239",
"country": "SE"
}
},
"external_id": "ORDER-1"
}

Response

HTTP/1.1 200 OK
Date: Fri, 29 Jul 2022 09:08:37 GMT
Content-Type: application/json
Content-Length: 274
Connection: close
Vary: Accept-Encoding
x-trace-id: S20220729090837JD4Y816EFC930Z06

{
"session": {
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"status": "COMPLETE",
"updated_at": "2022-07-29T09:08:37Z",
"cart": {
"total_value": 129900,
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"attributes": [
"shoes",
"indigo",
"class_one"
],
"quantity": 1
}
],
"cart_id": "unique_id"
},
"delivery_groups": [
{
"items": [
{
"sku": "SKU12345"
}
],
"shipping": {
"delivery_type": "instore",
"carrier": "Ingrid",
"product": "Pickup in Store",
"supports": {
"search": true
},
"warehouse": {
"address": {
"name": "Ingrid Swedish Warehouse",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.320672,
"lng": 18.035503
}
}
},
"carrier_product_id": "ProffsmagasinetBOX"
},
"category": {
"id": "to-store-32e78a504919437fa8e191adc389aaaa",
"name": "To Store",
"presented_category_name": "Delivery To Store"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2022-07-29T16:00:00+02:00",
"latest": "2022-07-29T16:00:00+02:00"
},
"customer_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
},
"carrier_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
}
},
"tos_id": "01G94KDZM0CS7WD3E9VYDWXR45",
"external_id": "ORDER-1",
"addresses": {
"location": {
"external_id": "I1",
"name": "Ingrid HQ",
"address": {
"name": "Ingrid HQ",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.3207318,
"lng": 18.0335876
}
},
"distance": {
"walking": {
"value": 1780,
"duration": 21
},
"driving": {
"value": 3097,
"duration": 6
}
}
},
"customer": {
"name": "Erik Johansson",
"address_lines": [
"Industrigatan 5"
],
"city": "Stockholm",
"postal_code": "11239",
"country": "SE"
},
"search_address": {
"postal_code": "11239",
"country": "SE",
"coordinates": {
"lat": 59.33122199302237,
"lng": 18.030565761645196
}
}
}
}
]
}
}
Note

The difference between the search address (used in session create and update requests) and the customer address (used in session complete request) is that the first one simply points us to which area package should be delivered, but it doesn't need to be customer real address. The customer address must be provided by the merchant.

For example, if you want to have a package delivered close to your work, you can fill search address with your office address. The customer is a customer home address. It allows performing fraud detection if someone is ordering an expensive item and customer and search addresses are distant to each other. The merchant could compare both addresses and verify if the order is valid by contacting the customer before shipping goods.

Get Session

The session.get method is used to fetch an active or completed session.

At any point of a session lifetime, session can be fetched using session.get call. The only argument to this call is the ID of the session.

The response contains the current state of a session and its format is the same as in examples above for creating and updating sessions. The session should never change during this call, since this is non-mutating call. If you want to fetch the fresh shipping options (e.g. making sure that expiration time slots are not stale), consider using session.pull, because it guarantees that the session state is fresh. Be aware that extensive usage of session.pull can cause concurrent session updates.

Generic Flow

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when fetching a previously created session and rendering the shipping selector for that session in the checkout page.

sequenceDiagram participant C as Customer participant M as Merchant participant A as Delivery Checkout API C->>M: Load the checkout page M->>A: Call /session.get A->>M: Return shipping selector html snippet and session state M->>C: Render shipping selector html snippet on the page
  1. Customer loads the checkout page.
  2. Merchant calls the session.get method.
  3. Delivery Checkout API returns a new Session and the html_snippet to render shipping selector.
  4. Merchant renders html_snippet in the checkout page.

Example Calls

Request

GET /v1/delivery_checkout/session.get?checkout_session_id=VM2-678b4f25ac5f43748be23eff5a59b344 HTTP/1.1
Host: api.ingrid.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer base64-encoded-api-token


Response

HTTP/1.1 200 OK
Date: Fri, 29 Jul 2022 09:08:37 GMT
Content-Type: application/json

Connection: close
Vary: Accept-Encoding
x-trace-id: S20220729090837KEWA1JZ4E36MHEYW

{
"session": {
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"status": "COMPLETE",
"updated_at": "2022-07-29T09:08:37Z",
"cart": {
"total_value": 129900,
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"attributes": [
"shoes",
"indigo",
"class_one"
],
"quantity": 1
}
],
"cart_id": "unique_id"
},
"delivery_groups": [
{
"items": [
{
"sku": "SKU12345"
}
],
"shipping": {
"delivery_type": "instore",
"carrier": "Ingrid",
"product": "Pickup in Store",
"supports": {
"search": true
},
"warehouse": {
"address": {
"name": "Ingrid Swedish Warehouse",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.320672,
"lng": 18.035503
}
}
},
"carrier_product_id": "ProffsmagasinetBOX"
},
"category": {
"id": "to-store-32e78a504919437fa8e191adc389aaaa",
"name": "To Store",
"presented_category_name": "Delivery To Store"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2022-07-29T16:00:00+02:00",
"latest": "2022-07-29T16:00:00+02:00"
},
"customer_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
},
"carrier_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
}
},
"tos_id": "01G94KDZM0CS7WD3E9VYDWXR45",
"external_id": "ORDER-1",
"addresses": {
"location": {
"external_id": "I1",
"name": "Ingrid HQ",
"address": {
"name": "Ingrid HQ",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.3207318,
"lng": 18.0335876
}
},
"distance": {
"walking": {
"value": 1780,
"duration": 21
},
"driving": {
"value": 3097,
"duration": 6
}
}
},
"customer": {
"name": "Erik Johansson",
"address_lines": [
"Industrigatan 5"
],
"city": "Stockholm",
"postal_code": "11239",
"country": "SE"
},
"search_address": {
"postal_code": "11239",
"country": "SE",
"coordinates": {
"lat": 59.33122199302237,
"lng": 18.030565761645196
}
}
}
}
]
},
"html_snippet": "<div id='ingrid'> ... </div>"
}

Pull Session

The session.pull method is used to fetch an existing session data.

At any point of a session lifetime, session can be fetched using session.pull call. The only argument to this call is ID of the session.

The response contains the current state of a session and its format is the same as in examples above for creating and updating sessions. When some shipping options have expired or merchant configuration has changed, new shipping options might be fetched and new choices might be generated.

Call to this API endpoint can mutate session state. This is in contrary to session.get endpoint behavior, that gets the last session state and does not refresh it.

Generic Flow

The sequence diagram below describes the flow between the Customer, Merchant, Shipping Selector and Delivery Checkout API when fetching a previously created session and rendering the shipping selector for that session in the checkout page.

sequenceDiagram participant C as Customer participant M as Merchant participant A as Delivery Checkout API C->>M: Load the checkout page M->>A: Call /session.pull A->>M: Return shipping selector html snippet and session state M->>C: Render shipping selector html snippet on the page
  1. Customer loads the checkout page.
  2. Merchant calls the session.pull method.
  3. Delivery Checkout API returns a new Session and the html_snippet to render shipping selector.
  4. Merchant renders html_snippet in the checkout page.

Example Calls

Request

GET /v1/delivery_checkout/session.pull?checkout_session_id=VM2-678b4f25ac5f43748be23eff5a59b344 HTTP/1.1
Host: api.ingrid.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer base64-encoded-api-token


Response

HTTP/1.1 200 OK
Date: Fri, 29 Jul 2022 09:08:36 GMT
Content-Type: application/json

Connection: close
Vary: Accept-Encoding
x-trace-id: S20220729090836V5Y816NB1DDNKR0Z

{
"session": {
"checkout_session_id": "VM2-678b4f25ac5f43748be23eff5a59b344",
"status": "ACTIVE",
"updated_at": "2022-07-29T09:08:36Z",
"cart": {
"total_value": 129900,
"items": [
{
"sku": "SKU12345",
"name": "Saucony Shadow 6000",
"attributes": [
"shoes",
"indigo",
"class_one"
],
"quantity": 1
}
],
"cart_id": "unique_id"
},
"delivery_groups": [
{
"items": [
{
"sku": "SKU12345"
}
],
"shipping": {
"delivery_type": "instore",
"carrier": "Ingrid",
"product": "Pickup in Store",
"supports": {
"search": true
},
"warehouse": {
"address": {
"name": "Ingrid Swedish Warehouse",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.320672,
"lng": 18.035503
}
}
},
"carrier_product_id": "ProffsmagasinetBOX"
},
"category": {
"id": "to-store-32e78a504919437fa8e191adc389aaaa",
"name": "To Store",
"presented_category_name": "Delivery To Store"
},
"pricing": {
"currency": "SEK",
"price": 2900,
"price_components": [
{
"type": "PRICE_COMPONENT_TYPE_SHIPPING",
"value": 2900
}
]
},
"selection": "PRESELECTED_CHOICE",
"delivery_time": {
"pickup_from_merchant": {
"earliest": "2022-07-29T16:00:00+02:00",
"latest": "2022-07-29T16:00:00+02:00"
},
"customer_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
},
"carrier_delivery_promise": {
"earliest": "2022-07-29T00:00:00+02:00",
"latest": "2022-07-29T00:00:00+02:00"
}
},
"addresses": {
"location": {
"external_id": "I1",
"name": "Ingrid HQ",
"address": {
"name": "Ingrid HQ",
"address_lines": [
"Mälarvarvsbacken 8"
],
"city": "Stockholm",
"postal_code": "11733",
"country": "SE",
"coordinates": {
"lat": 59.3207318,
"lng": 18.0335876
}
},
"distance": {
"walking": {
"value": 1780,
"duration": 21
},
"driving": {
"value": 3097,
"duration": 6
}
}
},
"search_address": {
"postal_code": "11239",
"country": "SE",
"coordinates": {
"lat": 59.33122199302237,
"lng": 18.030565761645196
}
}
}
}
]
},
"html_snippet": "<div id='ingrid'> ... </div>"
}

Errors

Concurrent updates

Session pull, update and complete calls can fail when another concurrent call is made, that updates the session resource. In that case, the response to this call would be a message with HTTP 409 Conflict code, and the call would have to be made again.

Last updated: Fri, Sep 30, 09:17 AM