Ingrid Shipping Adapter
Overview
The Ingrid Adapter integrates Ingrid Delivery Checkout with Norce Checkout. It enables merchants to offer dynamic shipping options including home delivery, pickup points, and scheduled delivery windows directly within their checkout flow. Changes made in Norce Checkout are synced with Ingrid and vice versa. Read more on Ingrid Developer Documentation.
Environments
There are three environments that you can use. Replace {slug} with your merchant slug.
| Environment | Address |
|---|---|
| Playground | https://{slug}.api-se.playground.norce.tech/checkout/ingrid-adapter |
| Stage | https://{slug}.api-se.stage.norce.tech/checkout/ingrid-adapter |
| Production | https://{slug}.api-se.norce.tech/checkout/ingrid-adapter |
Getting Started as a Partner
To use the Ingrid Shipping adapter, you need to set up your Ingrid account and configure the adapter in Norce Checkout Admin.
Prerequisites
Before configuring the adapter, ensure you have the following from Ingrid:
- API Key: Obtain your API key from your Ingrid account
- API URL: The Ingrid API endpoint for your environment (staging or production)
Ingrid API Environments
| Environment | Ingrid API URL |
|---|---|
| Production | https://api.ingrid.com |
| Staging | https://api-stage.ingrid.com |
Configuration
Add your configuration for the Ingrid Shipping adapter in Norce Checkout Admin. The configuration requires:
| Field | Description | Example Value |
|---|---|---|
apiSettings.apiKey | Your Ingrid API key | your-api-key |
apiSettings.apiUrl | Ingrid API URL | https://api-stage.ingrid.com |
adapter.internalUrl | Internal URL for backend callbacks | https://ingrid-adapter.checkout.playground.internal.norce.tech |
adapter.publicUrl | Public URL for client-side requests | https://{slug}.api-se.playground.norce.tech/checkout/ingrid-adapter |
Optional Configuration
| Field | Description | Default |
|---|---|---|
options.useAddressForm | Use Ingrid's integrated address form instead of search address mode. When enabled, Ingrid handles address collection and customer data flows from Ingrid to Norce. | false |
options.useMinimalSearchAddress | Only send country and postal code to Ingrid. Useful when full address validation causes issues. | false |
options.externalIdSource | Order property used as Ingrid's external ID. Options: OrderId or OrderCartReference. | OrderId |
options.deliveryGroupHeaderTemplate | Template for delivery group headers sent to Ingrid; {0} is replaced with the 1-based group number | Delivery {0} |
Example Configuration
{
"$schema": "https://checkout-configuration.norce.tech/schemas/ingrid_adapter.json",
"id": "ingrid_adapter",
"active": true,
"adapter": {
"internalUrl": "https://ingrid-adapter.checkout.playground.internal.norce.tech",
"publicUrl": "https://{slug}.api-se.playground.norce.tech/checkout/ingrid-adapter"
},
"apiSettings": {
"apiKey": "your-ingrid-api-key",
"apiUrl": "https://api-stage.ingrid.com"
},
"options": {
"useAddressForm": false,
"useMinimalSearchAddress": false,
"externalIdSource": "OrderId",
"deliveryGroupHeaderTemplate": "Delivery {0}"
}
}Create Shipping
To get an Ingrid Delivery Checkout session with shipping options, create a shipping using the Ingrid adapter.
POST /api/checkout/v1/orders/{order_id}/shippings
Host: {slug}.api-se.stage.norce.tech
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}The Ingrid adapter will fetch the order, map it to Ingrid's format, and create a session. The response contains the Norce shipping ID, the Ingrid session ID, and an HTML snippet for embedding the widget.
{
"shippingId": "sGMVlgVNMjCDxsdJaOwmklGEpjM",
"htmlSnippet": "<div id=\"shipwallet-container\">...</div>",
"sessionId": "VM2-a1bc234...",
"useAddressForm": false
}The adapter will register any hooks and notifications required to keep track of changes to the order, so you will not need to inform it of changes made to the order by other adapters.
Using the Response with the Ingrid Widget
The response contains an htmlSnippet that includes the Ingrid widget initialization script and container. Insert this snippet into your checkout page where you want the delivery options to appear.
<!-- Widget container - insert the htmlSnippet here -->
<div id="shipwallet-container">
<!-- The htmlSnippet from the API response goes here -->
</div>For detailed widget integration instructions, see the Ingrid Frontend Integration documentation.
<!-- Example: Embedding the Ingrid widget -->
<script>
// After calling the Create Shipping endpoint and receiving the response:
const response = /* response from POST /api/checkout/v1/orders/{order_id}/shippings */;
const orderId = /* your order ID */;
const shippingId = response.shippingId;
const merchant = /* your merchant ID */;
const channel = /* your channel ID */;
// Insert the HTML snippet into your page
document.getElementById('shipwallet-container').innerHTML = response.htmlSnippet;
// Initialize the Ingrid event listener
window._sw = window._sw || function() { (window._sw.q = window._sw.q || []).push(arguments); };
// Listen for shipping option changes
_sw('on', 'shipping_option_changed', async function(data) {
// Call the shipping-changed endpoint to update Norce
await fetch(`/api/checkout/v1/callback/orders/${orderId}/shippings/${shippingId}/shipping-changed`, {
method: 'POST',
headers: {
'x-merchant': merchant,
'x-channel': channel,
'Authorization': 'Bearer ' + token
}
});
});
// Only needed when using address form mode (useAddressForm: true)
_sw('on', 'address_changed', async function(data) {
await fetch(`/api/checkout/v1/callback/orders/${orderId}/shippings/${shippingId}/customer-changed`, {
method: 'POST',
headers: {
'x-merchant': merchant,
'x-channel': channel,
'Authorization': 'Bearer ' + token
}
});
});
</script>Get Shipping Session
To retrieve an existing Ingrid session with the latest shipping data, use the GET endpoint:
GET /api/checkout/v1/orders/{order_id}/shippings/{shipping_id}
Host: {slug}.api-se.stage.norce.tech
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}This returns the same structure as the create endpoint, allowing you to re-render the widget if needed.
Client-Side Callbacks
Ingrid will not inform the adapter directly of all changes made through the Ingrid widget. When a user interacts with the widget (selects a shipping option or enters address information), the widget triggers events. You need to listen for these events and call the Norce Ingrid Adapter API to update the order.
For more details, see the Ingrid Frontend Integration documentation.
Listening to Ingrid Events
The Ingrid widget uses a global _sw function to register event listeners. Set up your listeners after the widget is loaded:
// Initialize the Ingrid event listener
window._sw = window._sw || function() { (window._sw.q = window._sw.q || []).push(arguments); };
// Called when customer selects a shipping option
_sw('on', 'shipping_option_changed', async function(data) {
await fetch(`/api/checkout/v1/callback/orders/${orderId}/shippings/${shippingId}/shipping-changed`, {
method: 'POST',
headers: {
'x-merchant': merchant,
'x-channel': channel,
'Authorization': 'Bearer ' + token
}
});
});The shipping-changed and customer-changed endpoints do not require a request body. The adapter fetches the current session state directly from Ingrid when called.
Shipping Changed
When the shipping_option_changed event is triggered, call the shipping changed endpoint to update the Norce order with the user's selection:
POST /api/checkout/v1/callback/orders/{order_id}/shippings/{shipping_id}/shipping-changed
Host: {slug}.api-se.stage.norce.tech
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}Customer Changed (Address Form Mode Only)
When using address form mode (useAddressForm: true), listen for the address_changed event and call the customer changed endpoint to sync address data from Ingrid to Norce:
POST /api/checkout/v1/callback/orders/{order_id}/shippings/{shipping_id}/customer-changed
Host: {slug}.api-se.stage.norce.tech
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}Automatic Updates
The adapter automatically handles updates when the Norce order changes. These hooks are registered automatically when creating the session, so no action is required from the partner.
Cart Changed
When items in the cart change, the adapter receives a callback and updates the Ingrid session with the new cart data. This ensures that shipping prices and availability are always accurate based on the current cart contents. Cart changes replace the entire Norce Checkout cart, which clears the delivery group indices used for split shipment, so an API consumer that uses split shipment must re-apply them with its own hook. See Required Cart Hook for Ingrid Split Shipment.
Customer Changed (Search Address Mode)
When customer address changes in Norce and the adapter is configured with useAddressForm: false (the default), the adapter automatically updates Ingrid with the new address. This hook is not registered when using address form mode, as customer data flows from Ingrid to Norce instead.
State Changed
When the order state changes, the adapter reacts accordingly:
- Processing: Validates the Ingrid session to ensure it's ready for completion
- Accepted: Completes the Ingrid session, finalizing the delivery selection
Completing the Session
As you complete your order (usually driven by a payment adapter), the Ingrid adapter will react to the state change and complete the session in Ingrid. The shipping object will then contain the Ingrid delivery reference (tos_id) in the tmsReference field.
Widget Integration
The Ingrid Delivery Checkout widget is embedded in your frontend using the htmlSnippet returned from the adapter. The widget provides a user interface for selecting shipping options, pickup points, and delivery time windows.
For detailed widget integration instructions, see the Ingrid Frontend Integration documentation.
Integration Modes
The adapter supports two integration modes controlled by the useAddressForm configuration option:
Search Address Mode (default): Customer address from the Norce order is sent to Ingrid. Delivery options are displayed based on the provided address. Address changes in Norce are automatically synced to Ingrid via backend hooks.
Address Form Mode: Ingrid's integrated address form handles address collection. Customer information flows from Ingrid back to the Norce order via the client-side customer-changed callback.
Promotions and Discounts
The Ingrid Adapter handles two types of discounts: item-level discounts (reflected in per-item pricing) and shipping discounts (forwarded to Ingrid as voucher codes). Promotions flow one way — from Norce to Ingrid. No promotion data is mapped back from Ingrid to Norce.
Setup Requirements
For shipping discount vouchers to work end-to-end, both Norce Commerce and Ingrid must be configured with matching rules:
In Norce Commerce:
- Create a promotion in Norce Commerce Admin using the "Discount freight" effect type (the effect type that targets shipping costs rather than item prices).
- Assign a discount code (voucher code) to the promotion.
- Optionally configure promotion attributes (such as
freightDiscountPct).
The Norce Adapter automatically classifies promotions with the "Discount freight" effect as type = shipping on the Norce Checkout order. All other promotions are classified as type = item.
In Ingrid:
- Configure a shipping rule in Ingrid that matches the same voucher code used in Norce Commerce (e.g., a free shipping rule triggered by the code
freefreight). - Coordinate with your Ingrid account manager to ensure matching voucher rules are set up.
The voucher codes sent to Ingrid must match rules configured on the Ingrid side. If Ingrid does not have a matching rule for a given voucher code, the code is ignored and no shipping discount is applied.
How Discounts Are Mapped (Norce → Ingrid)
When the Ingrid Adapter creates or updates a session, it maps discounts as follows:
| What | How |
|---|---|
| Item discount per line | (originalTotal.includingVat − total.includingVat) × 100 → cart.items[].discount |
| Item undiscounted price | price.includingVat × 100 → cart.items[].price |
| Shipping discount codes | cart.discounts[type=shipping].code → cart.vouchers |
| Shipping discount attributes | discount.attributes → cart.attributes (flattened as key=value) |
| Cart total (post-discount) | cart.total.includingVat × 100 → cart.total_value |
| Cart total discount | Not set by the adapter — cart.total_discount defaults to 0 |
Item-level discounts (type = item) are not forwarded as vouchers — their effect is already captured in the per-item discount field. Only shipping discounts produce voucher entries.
When the Ingrid session is mapped back to Norce, no promotion data is extracted. The entire Ingrid session is serialized as raw JSON into the shippingData attribute on the Norce shipping object.
Example
Norce Checkout order with a shipping discount:
{
"cart": {
"discounts": [
{
"type": "shipping",
"name": "free freight",
"code": "freefreight",
"attributes": { "code": "free_freight" }
}
],
"items": [
{ "sku": "PROD-001", "quantity": 1, "price": { "includingVat": 1295.00 }, "total": { "includingVat": 1295.00 }, "originalTotal": { "includingVat": 1295.00 } },
{ "sku": "PROD-002", "quantity": 1, "price": { "includingVat": 299.00 }, "total": { "includingVat": 299.00 }, "originalTotal": { "includingVat": 299.00 } }
],
"total": { "includingVat": 1594.00 }
}
}Resulting Ingrid session request:
{
"cart": {
"vouchers": ["freefreight"],
"attributes": ["code=free_freight", "b2c"],
"total_value": 159400,
"items": [
{ "sku": "PROD-001", "discount": 0, "price": 129500, "quantity": 1 },
{ "sku": "PROD-002", "discount": 0, "price": 29900, "quantity": 1 }
]
}
}The shipping discount code "freefreight" is sent as a voucher. The discount attribute "code": "free_freight" is flattened to "code=free_freight" in the cart attributes. Item discounts are 0 because each item's originalTotal equals its total. If multiple shipping discounts are applied, all codes are collected into the cart.vouchers list.
Split Shipment
Split shipment in the Ingrid Shipping Adapter means that a single Ingrid Delivery Checkout session is split into multiple deliveries — called delivery groups — where each group can have its own carrier, shipping option, pickup location, and price. Split shipment is used when items in the same Norce Checkout cart cannot ship together, for example when they come from different warehouses or suppliers, or when only some items are in stock. The customer selects a delivery option per group in the Ingrid widget, and the Norce Checkout shipping object receives one delivery entry per group.
Using split shipment with the Ingrid Shipping Adapter has two parts, and both are the responsibility of the API consumer:
- Assigning items to delivery groups — set
cart.items[].logistics.delivery.groupon the Norce Checkout order. - Keeping the group assignments alive — the group values are wiped every time the cart changes, so the API consumer must register a Norce Checkout hook that re-applies them. Without that hook, split shipment appears to work until the customer changes the cart, and then silently collapses back into a single delivery.
Assigning Cart Items to Ingrid Delivery Groups
Splitting in the Ingrid Shipping Adapter is driven entirely by the logistics.delivery.group index on each item in the Norce Checkout cart. Items that share the same group index belong to the same shipment. The Ingrid Adapter groups the cart items by this index and sends one Ingrid cart group per index. The field exists in both the V0 and the V1 Norce Checkout Order API, and a missing or null value is treated as group 0.
{
"id": "order-123",
"cart": {
"items": [
{
"sku": "PROD-001",
"quantity": 1,
"logistics": { "delivery": { "group": 0 } }
},
{
"sku": "PROD-002",
"quantity": 2,
"logistics": { "delivery": { "group": 1 } }
}
]
}
}The Ingrid Adapter does not define or enforce any logic for splitting the cart. Instead, the API consumer is responsible for assigning the logistics.delivery.group index on each Norce Checkout cart item based on its own business rules (for example per warehouse, per supplier, or per availability date). The adapter only forwards the grouping it receives.
Ingrid Delivery Group Rules and Constraints
The following rules apply to logistics.delivery.group when the Ingrid Shipping Adapter maps a Norce Checkout cart to an Ingrid session:
- Default behavior (single shipment): If every cart item has group index
0— the default when no group is set — no groups are sent to Ingrid and the order is treated as a single shipment. - Sequential indices required: Group indices must be sequential, start at
0, and contain no gaps (for example0,1,2). A gap, such as items in groups0and2with no item in group1, causes a validation error with error codeingrid-delivery-group-gap(ErrorCode.Ingrid.DeliveryGroupGap) and the messageDelivery group indices must be sequential without gaps.Because the Ingrid Adapter runs inside the hook chain of the cart change, this validation error fails the entire cart change and rolls it back. An API consumer that assigns delivery groups must therefore renumber the remaining groups when an item is removed. - Groups are per cart item line: The group is assigned per cart item line, not per unit. The quantity of a single cart item line cannot be spread across two delivery groups. To ship two units of the same SKU in different groups, use two separate cart item lines.
- Group headers: Each group is sent to Ingrid as a cart group with a
header. The header text is controlled by the optional configuration fieldoptions.deliveryGroupHeaderTemplate, which defaults to"Delivery {0}", where{0}is replaced with the 1-based group number. With the default template, groups are labelled "Delivery 1", "Delivery 2", and so on. - Group ids: Group ids sent to Ingrid are generated as
{orderId}-group-{index}, using the zero-based group index (for exampleorder-123-group-0).
Required Cart Hook for Ingrid Split Shipment
Delivery group assignments do not survive a cart change in Norce Checkout. To use split shipment with the Ingrid Shipping Adapter, the API consumer must register a hook that re-applies the delivery groups on every cart change.
Why the delivery group values are lost: The Norce Commerce basket has no concept of delivery groups. On every cart change — quantity update, added or removed item, discount code, price recalculation, or basket webhook — the Norce Commerce Adapter rebuilds the cart from the basket and replaces the entire cart on the Norce Checkout order. The cart model of the Norce Commerce Adapter has no delivery property, so the cart it sends never contains logistics.delivery, and the Norce Checkout Order API applies the update as a full replace of /cart without merging previous values. The result is that all logistics.delivery.group values are reset to null (which means group 0) on every cart change.
There is no built-in mechanism in Norce Checkout or in the Ingrid Shipping Adapter that preserves logistics.delivery.group across cart changes. An API consumer that uses split shipment must register a hook that re-assigns the delivery group indices on every cart change. Without it, an order that started as a split shipment collapses into a single delivery as soon as the cart changes.
Registering the hook: Register the hook once per order, typically directly after creating the order. For a general introduction to hooks in Norce Checkout, see Hooks.
POST /api/v1/checkout/orders/{orderId}/hooks
Host: {slug}.api-se.{environment}.norce.tech/checkout/order
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}
Content-Type: application/json
{
"adapterId": "{your-adapter-or-integration-id}",
"reference": "assign-delivery-groups",
"description": "Re-assigns Ingrid delivery group indices on cart changes",
"scope": "/cart",
"target": "/cart",
"invoke": "https://your-service.example.com/hooks/orders/{order_id}/assign-delivery-groups",
"version": "v1"
}scopeis the path in the order the hook subscribes to./cartmeans the hook is invoked whenever the cart changes.targetis the part of the order the hook is allowed to patch. Patch operations outside the target path are rejected by the Norce Checkout Order API.invokeis the endpoint of the API consumer. The Norce Checkout Order API sends the full order as the request body and expects a JSON Patch document in the response. The substring{order_id}in the URL is replaced with the id of the order before the call is made.referenceis a stable identifier for the hook across orders, used to track the hook in the event log, anddescriptiondocuments its purpose.versionis the version of the order body the hook receives. Usev1to receive the V1 order model.
Hook contract: On every cart change, the endpoint receives the full Norce Checkout order and must respond with HTTP 200 and a JSON Patch document (RFC 6902) that sets the delivery group of each cart item. Respond with an empty array [] when nothing needs to change.
[
{ "op": "add", "path": "/cart/items/0/logistics/delivery", "value": { "group": 0 } },
{ "op": "add", "path": "/cart/items/1/logistics/delivery", "value": { "group": 1 } },
{ "op": "add", "path": "/cart/items/2/logistics/delivery", "value": { "group": 0 } }
]Rules for implementing the delivery group hook:
- Patch the
deliveryobject, not thegroupfield. After a cart change, the cart item usually has nodeliveryobject at all, and a patch operation whose parent path is missing is rejected withFor operation 'add', the target location specified by path '/cart/items/0/logistics/delivery/group' was not found., which fails the whole cart change. Patching/cart/items/{index}/logistics/deliverywith a value such as{ "group": 1 }both creates and overwrites the delivery object and keeps the other logistics fields on the item. If a cart item has nologisticsobject either, patch/cart/items/{index}/logisticsinstead, and include the item's existing logistics fields from the request body in the value, otherwise they are lost. - Patch only the delivery data. Do not respond with a patch that replaces the whole cart or whole cart items. If the full order is deserialized into a consumer-side model and echoed back, any field the model does not know about is silently dropped, and value precision (for example on decimals) can be lost.
- Keep the group indices contiguous. If the customer removes the last item of group
1while group2still has items, the hook must renumber group2to1. Otherwise the Ingrid Adapter rejects the cart withingrid-delivery-group-gapand the entire cart change fails and is rolled back. - Do not call the Norce Checkout Order API from inside the hook. Mutating the order from inside a hook starts a second hook chain that races the current one. Returning patch operations is the only safe way to write during a hook.
- Use the order from the request body, not a fresh
GETon the order. AGETduring the hook chain returns the state from before the ongoing change. - Be fast and reliable. The hook is synchronous within the checkout flow. A non-2xx response blocks the cart change and triggers a best-effort rollback of the hooks that were already invoked.
Why the hook runs before the Ingrid Adapter: The Norce Checkout Order API invokes hooks ordered by their target, with /cart (sort order 3) before /shippings (sort order 4). The Ingrid Adapter registers its own hooks subscribing to /cart, /customer, and /state, all with target /shippings. Within a single cart-change transaction, the sequence is therefore:
- The Norce Commerce Adapter replaces
/cart, and the delivery group values are wiped. - The hook of the API consumer (target
/cart) re-applies the delivery group indices to the working copy of the order. - The Ingrid Adapter hook (target
/shippings) maps the corrected cart into the Ingrid session. - Everything is persisted in a single write, and only if every hook succeeded.
Ingrid Delivery Groups Sent to Ingrid
The Ingrid Shipping Adapter maps the Norce Checkout cart items into cart.groups on the Ingrid session request, one group per distinct logistics.delivery.group index. The example below is the Ingrid session request produced by the two-group Norce Checkout cart for order order-123 with PROD-001 in group 0 and PROD-002 in group 1.
{
"cart": {
"groups": [
{
"group_id": "order-123-group-0",
"header": "Delivery 1",
"contents": [
{ "sku": "PROD-001", "quantity": 1 }
]
},
{
"group_id": "order-123-group-1",
"header": "Delivery 2",
"contents": [
{ "sku": "PROD-002", "quantity": 2 }
]
}
]
}
}How Ingrid Delivery Groups Are Mapped Back to Norce Checkout
When the Ingrid Adapter maps an Ingrid session back to the Norce Checkout shipping object, each Ingrid delivery group becomes a separate entry in the shipping deliveries list. Each delivery carries its own reference (the Ingrid tos_id of that group), deliveryDetails (carrier, carrier product id, delivery class, product, pickup location), addons, price, vatRate, and items (sku and quantity).
Aggregation rules on the Norce Checkout shipping object when multiple Ingrid delivery groups exist:
total: the sum of all deliveries' prices, both including and excluding VAT. It is not taken from a single group.name: reflects the selected shipping option(s). With a single delivery group, it is the carrier product name (for exampleFedEx International Connect Plus), falling back to the carrier name. With multiple delivery groups, it is the comma-joined list of distinct carrier names (for exampleFedEx, PostNord).- Root-level fields: fields at the root of the shipping object such as
tmsReference,deliveryDetails, andaddonsare populated from the first delivery group for backward compatibility with integrations that expect a single shipment. Read thedeliverieslist to get per-shipment data. shippingData: the complete Ingrid session, including all delivery groups, is stored in theshippingDataattribute on the Norce Checkout shipping object as a JSON-encoded string. Consumers must parse that string to read the Ingrid session, as shown in the example below.
The deliveries list exists only in the shipping model of the V1 Norce Checkout Order API. Consumers on V0 get the backward-compatible root-level fields plus the full Ingrid session in the shippingData attribute.
{
"shippings": [
{
"tmsReference": "01KGHX8V4MHCT77MT9DCGP4WC2",
"deliveryDetails": {
"carrier": "Best Transport",
"carrierProductId": "TerminalCollect",
"class": "pickup",
"product": {
"reference": "terminal-collect-0c062b9fec324907974e9a59b7dc9f7e",
"name": "Best Terminal Collect"
}
},
"deliveries": [
{
"reference": "01KGHX8V4MHCT77MT9DCGP4WC2",
"deliveryDetails": { "carrier": "Best Transport", "class": "pickup" },
"price": { "includingVat": 0, "excludingVat": 0 },
"vatRate": 0.25,
"items": [{ "sku": "PROD-001", "quantity": 1 }]
},
{
"reference": "01KGHX8V4MVJAH0PPDGQWVHCD7",
"deliveryDetails": { "carrier": "Best Transport", "class": "pickup" },
"price": { "includingVat": 0, "excludingVat": 0 },
"vatRate": 0.25,
"items": [{ "sku": "PROD-002", "quantity": 2 }]
}
],
"attributes": {
"shippingData": "{ ... full Ingrid session including delivery_groups ... }"
}
}
]
}Ingrid Split Shipment Checklist for API Consumers
To use split shipment with the Ingrid Shipping Adapter, an API consumer must:
- Use the V1 Norce Checkout Order API if the per-delivery
deliverieslist is needed on the completed shipping. V0 consumers read the root-level shipping fields and theshippingDataattribute instead. - Register a hook with
scope/cartandtarget/carton every order that needs split shipment, directly after creating the order. - In the hook, read the cart items from the request body, decide the grouping (for example per warehouse or per stock status), and respond with
addpatch operations for/cart/items/{index}/logistics/deliverywith the value{ "group": {group index} }, keeping the group indices sequential from0. - Renumber the delivery groups when an item is removed, so that no gap appears and the cart change is not rejected with
ingrid-delivery-group-gap. - On order completion, read
shippings[].deliveries[]for the per-delivery Ingridtos_idvalues (V1), or parse theshippingDataattribute (V0, or when full Ingrid detail is needed). - Optionally configure
options.deliveryGroupHeaderTemplateon the Ingrid Adapter configuration to control the group headers shown in the Ingrid widget.
Remove Shipping
To remove an Ingrid shipping session from an order:
POST /api/checkout/v1/orders/{order_id}/shippings/{shipping_id}/remove
Host: {slug}.api-se.stage.norce.tech
x-merchant: {merchant}
x-channel: {channel}
Authorization: Bearer {token}This will mark the shipping as removed in the Norce order.
Troubleshooting
Common Errors
- Validation Error: Ensure order has country, culture, and currency set before creating a session.
- 409 Conflict: An Ingrid shipping already exists for this order.
- Empty Cart Error: Order must have at least one item.
- Session Expired: Create a new shipping session.
- Delivery Group Gap: Group indices must be sequential without gaps. Delivery group indices on the Norce Checkout cart items (
logistics.delivery.group) must start at0with no missing index (for example0,1,2). A gap fails the whole cart change and rolls it back, so the delivery group hook of the API consumer must renumber the remaining groups when an item is removed. Error code:ingrid-delivery-group-gap. - Split Shipment Collapses Into One Delivery: If an Ingrid split shipment turns back into a single delivery after the customer changes the cart, the delivery group indices were wiped by the cart update and not re-applied. Delivery groups are not preserved across cart changes in Norce Checkout, so the API consumer must register a hook subscribing to
/cartwith target/cartthat re-assignslogistics.delivery.groupon every cart change. See Required Cart Hook for Ingrid Split Shipment.
Shipping States
| State | Description |
|---|---|
intent | Session created, awaiting customer selection |
processing | Order being processed, session validated |
confirmed | Session completed successfully |
removed | Shipping removed from order |