# Working with baskets
A core part to the shopping experience using Norce Commerce Services is the Basket. This is the container to the list of
items the visitor is interested in. The basket in Norce contains a lot of functionality and is dependent on many
business rules that are evaluated and applied for every action the visitor does from your commerce application.
Aside from the most common use of the basket object (the cart), there is also other ways to use it. Like wish lists,
approval/attests, saved for later, sent to punch out, subscriptions/recurring orders, etc. These functions are not
addressed in this document.
- [The full Basket Schema](/api-reference/schemas/shopping#basket)
- Check out the examples
in [Postman](https://documenter.getpostman.com/view/2973406/2sA35MzK14#d8eb437c-32b1-4dc3-a867-1bab2f923d2d)
as well.
details
summary
An example basket
```JSON
{
"Id": 6600304,
"CustomerId": null,
"CompanyId": null,
"SalesContactId": null,
"StatusId": 3,
"CurrencyId": 2,
"CurrencyCode": "SEK",
"Comment": null,
"OrderReference": null,
"DiscountCode": null,
"ReferId": null,
"ReferUrl": null,
"ValidTo": null,
"IsEditable": true,
"Items": [
{
"Id": 16030464,
"LineNo": 1,
"ParentLineNo": null,
"ProductId": 31234584,
"PartNo": "PRD0001270",
"ManufacturerPartNo": "T540XP",
"Name": "T540XP",
"SubHeader": "
Detta är en kort beskrivning.
",
"ThumbnailImage": "2/thumb_p31234584.jpg",
"FlagIdSeed": "915,1884",
"Type": 1,
"PriceDisplay": 5743.20,
"Price": 0.00,
"PriceOriginal": 5743.20,
"Cost": 5734.34,
"VatRate": 1.2500,
"Quantity": 1.000,
"UOM": "st",
"UOMCount": 1.000,
"Comment": null,
"PriceListId": 4654,
"ReferId": null,
"ReferUrl": null,
"IsEditable": true,
"IsDiscountable": true,
"Info": [
{
"TypeId": 209,
"Value": "",
"Code": "bit_size"
},
{
"TypeId": 241,
"Value": "",
"Code": "bit_del_time"
},
{
"TypeId": 95,
"Value": "",
"Code": "bit_additionalinformation"
}
],
"OptionalItems": [],
"OnHandValue": 0.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": null,
"PromotionIdSeed": "",
"ImageKey": "39e4b7ec-12d8-4f6e-b9c1-cbd7334190e1",
"ManufacturerName": "Husqvarna",
"CategoryId": 41722,
"OnHand": {
"Value": 0.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": null,
"LastChecked": null,
"IsActive": false,
"IsReturnable": true,
"Info": null
},
"OnHandSupplier": {
"Value": 200.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 7,
"LastChecked": null,
"IsActive": true,
"IsReturnable": true,
"Info": null
},
"PriceRecommended": 7000.00,
"ManufacturerId": 1685,
"UniqueName": "t540xp",
"StatusId": 1,
"StockDisplayBreakPoint": null,
"PriceCatalog": null,
"IsBuyable": true,
"SubDescription": null,
"CategoryIdSeed": "41722",
"RecommendedQuantity": 4.000,
"IsRecommendedQuantityFixed": false,
"AppliedPromotions": [],
"RequirementPromotionIdSeed": "5093",
"IsSubscribable": false,
"DescriptionHeader": "Husqvarna T540XP",
"IsPriceManual": false,
"PriceStandard": 6375.20,
"EanCode": "123123123123123",
"CostUnit": 0.00,
"PriceDisplayIncVat": 7179.00
},
{
"Id": 16030465,
"LineNo": 2,
"ParentLineNo": null,
"ProductId": 24706222,
"PartNo": "PRD0001212",
"ManufacturerPartNo": "FREIGHT01",
"Name": "Freight",
"SubHeader": null,
"ThumbnailImage": null,
"FlagIdSeed": "915",
"Type": 3,
"PriceDisplay": 0.00,
"Price": 0.00,
"PriceOriginal": 0.00,
"Cost": 0.00,
"VatRate": 1.25,
"Quantity": 1.000,
"UOM": "st",
"UOMCount": 1.000,
"Comment": null,
"PriceListId": 1,
"ReferId": null,
"ReferUrl": null,
"IsEditable": true,
"IsDiscountable": true,
"Info": [
{
"TypeId": 209,
"Value": "",
"Code": "bit_size"
},
{
"TypeId": 241,
"Value": "",
"Code": "bit_del_time"
},
{
"TypeId": 95,
"Value": "",
"Code": "bit_additionalinformation"
}
],
"OptionalItems": [],
"OnHandValue": 0.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 0,
"PromotionIdSeed": null,
"ImageKey": null,
"ManufacturerName": "Miscellaneous",
"CategoryId": null,
"OnHand": {
"Value": 0.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 0,
"LastChecked": "/Date(1325504774807+0100)/",
"IsActive": true,
"IsReturnable": true,
"Info": null
},
"OnHandSupplier": {
"Value": 0.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": null,
"LastChecked": null,
"IsActive": false,
"IsReturnable": true,
"Info": null
},
"PriceRecommended": null,
"ManufacturerId": 4335,
"UniqueName": "freight",
"StatusId": 1,
"StockDisplayBreakPoint": null,
"PriceCatalog": null,
"IsBuyable": true,
"SubDescription": null,
"CategoryIdSeed": "",
"RecommendedQuantity": 1.000,
"IsRecommendedQuantityFixed": false,
"AppliedPromotions": [],
"RequirementPromotionIdSeed": null,
"IsSubscribable": false,
"DescriptionHeader": null,
"IsPriceManual": false,
"PriceStandard": 0.00,
"EanCode": "",
"CostUnit": 0.00,
"PriceDisplayIncVat": 0.00
},
{
"Id": 0,
"LineNo": 3,
"ParentLineNo": 1,
"ProductId": 31234588,
"PartNo": "PRD0001274",
"ManufacturerPartNo": "Underhållskit",
"Name": "Underhållskit Motorsåg",
"SubHeader": null,
"ThumbnailImage": "2/thumb_p31234588.png",
"FlagIdSeed": "915",
"Type": 1,
"PriceDisplay": 111.20,
"Price": 0.00,
"PriceOriginal": 111.20,
"Cost": 100.25,
"VatRate": 1.25,
"Quantity": 1,
"UOM": "st",
"UOMCount": 1.000,
"Comment": null,
"PriceListId": 1,
"ReferId": null,
"ReferUrl": null,
"IsEditable": false,
"IsDiscountable": true,
"Info": [
{
"TypeId": 209,
"Value": "",
"Code": "bit_size"
},
{
"TypeId": 241,
"Value": "",
"Code": "bit_del_time"
},
{
"TypeId": 95,
"Value": "",
"Code": "bit_additionalinformation"
}
],
"OptionalItems": [],
"OnHandValue": 12.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 0,
"PromotionIdSeed": "",
"ImageKey": null,
"ManufacturerName": "Husqvarna",
"CategoryId": 41722,
"OnHand": {
"Value": 12.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 0,
"LastChecked": null,
"IsActive": true,
"IsReturnable": true,
"Info": null
},
"OnHandSupplier": {
"Value": 133.000,
"IncomingValue": 0.000,
"NextDeliveryDate": null,
"LeadtimeDayCount": 5,
"LastChecked": "/Date(1487085555163+0100)/",
"IsActive": true,
"IsReturnable": true,
"Info": null
},
"PriceRecommended": null,
"ManufacturerId": 1685,
"UniqueName": "underhallskit-motorsag",
"StatusId": 1,
"StockDisplayBreakPoint": null,
"PriceCatalog": null,
"IsBuyable": true,
"SubDescription": null,
"CategoryIdSeed": "41722",
"RecommendedQuantity": 1.000,
"IsRecommendedQuantityFixed": false,
"AppliedPromotions": [],
"RequirementPromotionIdSeed": "",
"IsSubscribable": false,
"DescriptionHeader": null,
"IsPriceManual": false,
"PriceStandard": 0.00,
"EanCode": "345345345345345",
"CostUnit": 0.00,
"PriceDisplayIncVat": 139.00
}
],
"Info": [
{
"TypeId": 169,
"Value": "",
"Code": "bit_expecteddeliverydate"
},
{
"TypeId": 293,
"Value": "",
"Code": "bit_additionalorderinfo"
},
{
"TypeId": 445,
"Value": "",
"Code": "Norce_Gender"
},
{
"TypeId": 493,
"Value": "",
"Code": "recurring"
}
],
"Summary": {
"Items": {
"Amount": 5854.40,
"Vat": 1463.60,
"AmountIncVat": 7318.00
},
"Freigt": {
"Amount": 0.00,
"Vat": 0.00,
"AmountIncVat": 0.00
},
"Fees": {
"Amount": 0.00,
"Vat": 0.00,
"AmountIncVat": 0.00
},
"Total": {
"Amount": 5854.40,
"Vat": 1463.60,
"AmountIncVat": 7318.00
}
},
"AppliedPromotions": [
{
"Id": 5093,
"Name": "Add service",
"Header": "",
"ShortDescription": "",
"Description1": "",
"Description2": "",
"StartDate": null,
"EndDate": null,
"ImageKey": null,
"RequirementSeed": "3",
"DiscountCode": null,
"IsExcludedFromPriceCalculation": false,
"AllowProductListing": false,
"Images": [],
"ProductFilters": [
{
"ManufacturerId": null,
"CategorySeed": null,
"TypeId": null,
"ProductId": null,
"VariantProductId": null,
"PartNo": "PRD0001274",
"PricelistId": 1,
"FlagId": null
},
{
"ManufacturerId": null,
"CategorySeed": null,
"TypeId": null,
"ProductId": null,
"VariantProductId": null,
"PartNo": null,
"PricelistId": null,
"FlagId": 1884
}
],
"AppliedAmount": 0.00,
"EffectSeed": "5",
"FreightDiscountPct": null,
"IsStackable": true,
"AppliedAmountIncVat": 0.00
}
],
"IpAddress": "151.236.200.213",
"AttestedBy": null,
"TypeId": 1,
"DoHold": false,
"IsBuyable": true,
"InvoiceReference": null,
"PaymentMethodId": null,
"DeliveryMethodId": 1,
"SalesAreaId": 1
}
```
```XML
6600304
3
2
SEK
true
16030464
1
31234584
PRD0001270
T540XP
T540XP
<p>Detta är en kort beskrivning.</p>
2/thumb_p31234584.jpg
915,1884
1
5743.20
0.00
5743.20
5734.34
1.25
1
st
1.000
4654
true
true
209
bit_size
241
bit_del_time
95
bit_additionalinformation
0.000
0.000
39e4b7ec-12d8-4f6e-b9c1-cbd7334190e1
Husqvarna
41722
0.000
0.000
false
true
200.000
0.000
7
true
true
7000.00
1685
t540xp
1
true
41722
4.000
false
5093
false
Husqvarna T540XP
false
6375.20
123123123123123
0.00
7179.00
16030465
2
24706222
PRD0001212
FREIGHT01
Freight
915
3
0.00
0.00
0.00
0.00
1.25
1
st
1.000
1
true
true
209
bit_size
241
bit_del_time
95
bit_additionalinformation
0.000
0.000
0
Miscellaneous
0.000
0.000
0
2012-01-02T12:46:14.807
true
true
0.000
0.000
false
true
4335
freight
1
true
1.000
false
false
false
0.00
0.00
0.00
0
3
1
31234588
PRD0001274
Underhållskit
Underhållskit Motorsåg
2/thumb_p31234588.png
915
1
111.20
0.00
111.20
100.25
1.25
1
st
1.000
1
false
true
209
bit_size
241
bit_del_time
95
bit_additionalinformation
12.000
0.000
0
Husqvarna
41722
12.000
0.000
0
true
true
133.000
0.000
5
2017-02-14T16:19:15.163
true
true
1685
underhallskit-motorsag
1
true
41722
1.000
false
false
false
0.00
345345345345345
0.00
139.00
169
bit_expecteddeliverydate
293
bit_additionalorderinfo
445
Norce_Gender
493
recurring
5854.40
1463.60
7318.00
0.00
0.00
0.00
0.00
0.00
0.00
5854.40
1463.60
7318.00
5093
Add service
3
false
false
PRD0001274
1
1884
0.00
5
true
0.00
151.236.200.213
1
false
true
1
1
```
## The basket data model

The basket contains many properties, here are some important ones.
- `Id`, the identifier of the basket. For the visitors active basket, this is usually stored in a persisted cookie
- `Status`, basket can have different statuses, depending on the usage. For a cart the most common are *"Basket"* (3),
*"Ready for payment"* (7), *"Payment pending"* (12), *"Payment Accepted"* (8), *"Order"* (10).
- `Currency`, if the application allowed for different currencies this field can be changed. The basket will the convert
the prices and amounts to the chosen currency.
- `IsEditable` and `IsBuyable`, in some instances the basket is locked and cannot be updated by the visitor or not able
to be processed through a checkout. Some examples are when the basket has become an order, or during the checkout
process.
- `Summary`, this contains summary information on the total amount and freight.
- `Items`, are a collection of all the products added to the basket, with
- `Id`, the identifier of the `BasketItem` (this is required for the update calls)
- `LineNo`, a friendly number of the row
- `ParentLineNo`, for complex items (like packages), or for user-friendly grouping of items
- `ProductId` and `PartNo`, identifiers of the product. A basket item must be connected to a product in Norce Commerce
- `Type`, the product type
- `PriceDisplay`, the price in a friendly format, for read only
- `Quantity`, number of items in the basket
- `PriceListId`, the price list the price is based from
- `IsEditable`, in some instances the basket item cannot be updated by the visitor
Restrictions
Norce handles quite a lot of the basket business logic behind the scenes.
For example if you add an item to the basket that already exists, Norce does not increment the existing row´s quantity,
instead a new line is added to the basket. This is because many solutions needs to have this flexibility, for example: A
B2B sales model often needs to separate items into rows and add delivery or invoice references separately for each item.
*A common practice is to add these simplifications in your own backend in a service layer where your Norce Commerce
requests pass through. This lets you simplify the workflow specific to your needs.*
## The update pattern
When working with baskets there is a lot of possible changes that will happen to the basket for every action the visitor
does. Therefore, Norce Commerce Shopping Service always return the whole basket object whenever a change is done. A good
common practice is to have the basket stored in a cache, or (if concurrency is an issue i.e. if many clients work with
the same lists) ask for the basket first before mapping in your changes and then call the update in the API.

1. A user action has occurred.
2. A basket object is fetched, either from Norce Commerce or from a local cache
3. The changes are mapped into the basket item (from the model object)
4. The update is
called ([UpdateBasket](/api-reference/services/shoppingservice/openapi/basket/updatebasket2), [UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem)
or similar)
5. The whole basket is returned from Norce
6. The returned basket is mapped to a model object, written to a local cache and returned to the front end
A basket can change even without user action. For example the state of an item can change so that it is not buyable
anymore (not in stock anymore, status set to inactive, etc.) or a campaign or a promotion can stop being valid. This is
something that your application needs to take into consideration in the fault and exception handling.
### Context
There is a lot of contextual information on all gets and updates that you need to make sure to always send in to Norce
Commerce Services if you are using them, for example: `pricelistSeed`, `cultureCode`, `currencyId`. They are optional
but if you use any one of them in your application, they need to be passed in on all calls.
Another input variable of note is the `createdBy`, that should be passed in when a known user is working with their
baskets, if user is a guest/unknown set this to `1`.
## Lifecycle
### Create Basket
A basket is created when
the [CreateBasket](/api-reference/services/shoppingservice/openapi/basket/createbasket)
method is called. Preferably this is done when the first item(s) are added to the visitors' basket. You can create a
basket with default values, by passing in a whole basket object.
A good idea is to pass in `CustomerId` and `CompanyId` for logged-in users, default `PaymentMethodId` and default
`DeliveryMethodId`. Then you don't need to make these update calls in the checkout later.
### Add Items
There are several methods to add items to the basket - `InsertBasketItem`, `InsertBasketItems`,
`InsertBasketItemsWithChildren`, but also the `UpdateBasketItem` calls can increment the quantity on an existing item.
- [InsertBasketItem](/api-reference/services/shoppingservice/openapi/basket/insertbasketitem),
takes a basketitem as payload and appends it to the basket items collection, generating a LineNo and a unique Id to
the line.
- [InsertBasketItems](/api-reference/services/shoppingservice/openapi/basket/insertbasketitems),
takes a collection of basketitems as payload and appends them to the basket items collection.
- [InsertBasketItemWithChildren](/api-reference/services/shoppingservice/openapi/basket/insertbasketitems),
takes a collection of basketitems as its payload and appends them to the basket items collection. The first item in the collection is assigned as the parent of all the others.
- If you instead of appending wants to increment the quantity on already existing items you need to resolve it yourself
before calling a basket method.
Use [UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem)
or its sibling methods.
Recommended Quantity
Norce has a setting called `RecommendedQuantity` on the product, which suggest how many of the item that should
automatically be added to the cart, check this field when calling `InsertBasketItem`.
Note that this field is not *enforced* by Norce unless it is used in combination with the setting `IsRecommendedQuantityFixed` .
In that case, it is not possible to break a multiple of the `RecommendedQuantity` value.
Note that this field is not *enforced* by Norce unless it is also followed with the setting
`IsRecommendedQuantityFixed` - then it is not possible to break up a multiple of the `RecommendedQuantity` value.
### Remove Items
Use [DeleteBasketItem](/api-reference/services/shoppingservice/openapi/basket/deletebasketitem)
to removes one whole
row, [UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem)
calls can decrement quantity on existing items
and [ClearBasket](/api-reference/services/shoppingservice/openapi/basket/clearbasket)
removes all items on the basket.
Note
[UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem)
with quantity = 0 is the same as
calling [DeleteBasketItem](/api-reference/services/shoppingservice/openapi/basket/deletebasketitem).
### Change Basket
Use [UpdateBasket2](/api-reference/services/shoppingservice/openapi/basket/updatebasket2)
to change information on the header of the basket, like status, comment fields, etc. (mostly this is done in the
checkout process, see the [checkout guide](/developer-portal/app-development/working-with-the-checkout-process) )
### Change BasketItems
[UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem), [UpdateBasketItems](/api-reference/services/shoppingservice/openapi/basket/updatebasketitems)
lets you update item information on one or several items at the same time. A required field to send in to Norce Commerce
Shopping Service is the `Id` on the item, without it the update won't take. Make sure to keep it in your cache. Most
common field to update is the `Quantity` of course, but other fields are `Comment` and `Price`, read more about this
in [the checkout process](/developer-portal/app-development/working-with-the-checkout-process). Read also about some common scenarios under common
business logic [below](#common-business-logic).
### Remove or reopen the basket
When a basket has been successfully processed through the checkout the status is changed to *"Payment Accepted"* or a
bit later to *"Order"*. Then the basket is locked and should be removed from the active basket slot in session and
cookie. If a basket is still there your application should remove it silently and create a new basket when the end
customer needs it.
If anything happened on a basket that has moved further in the process, you might not be allowed to continue to make
changes on it. An easy way to keep the items and information on the basket is to create a new one passing in the old.
Everything that is allowed to be updated to the new one will be. You clone an old basket by
calling [CreateBasket](/api-reference/services/shoppingservice/openapi/basket/createbasket)
with the old one as payload.
See a postman
example [here](https://documenter.getpostman.com/view/2973406/2sA35MzK14#232bbe75-de6d-4949-814f-75bf1aeb6493).
## Common business logic
There are some more common business logic that is handled from the basket management code on your side.
### Overriding the price
In some scenarios, you might want to manually override the calculated price from Norce. This might be if you create a
sales quotation, or want to add an offer to the item from a 3rd party. To do this you must add your new price in
the [InsertBasketItem](/api-reference/services/shoppingservice/openapi/basket/insertbasketitem)
or [UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem)
in the field `Price`, and confirm this by specifically adding `IsPriceManual : true` as well.
> Note that the `Price` field takes the *unit price*, not the row amount.
Here is an example:
```json
{
"PartNo": "TestPartNo",
"Price": 160.00,
"Quantity": 1.000,
"Comment": "This is an insert of a manual price to a new row in the basket",
"PriceListId": 1,
"IsPriceManual": true
}
```
Then the returned basket item looks like this (shortened):
```json
{
"LineNo": 1,
"PartNo": "TestPartNo",
"PriceDisplay": 160.00,
"Price": 0.00,
"PriceOriginal": 160.00,
"Quantity": 1.000,
"PriceListId": 1,
"IsPriceManual": true,
"PriceDisplayIncVat": 200.00
}
```
Note that the field `Price` is 0 in the result, instead, the manual price is on `PriceDisplay`, just as with any normal
price, to recognize this price as a manual price you must check the `IsPriceManual` field.
### Lock the item to a price list
In some scenarios, you might want to lock the price to a specific price list. This will override any default "best price
validations" that Norce normally do on the basket items. This makes it possible to override Norce's best price
calculation and point to a specific price list that should be used.
Some use cases:
1. The solution should use a price list (agreement) that has a higher price than the current campaign, but might give
additional warranties or other prefered value to the customer.
2. The solution should set the reservation to a specific warehouse/location. Lock the item to a price list, connected to
this warehouse. Read
about [connected warehouses and reservation](/solution-portal/detailed-design/availability-structure#reservations),
for more info.
To lock the price to a price list, you must add `PriceListLocked : true` to the basket item in
the [InsertBasketItem](/api-reference/services/shoppingservice/openapi/basket/insertbasketitem)
or [UpdateBasketItem](/api-reference/services/shoppingservice/openapi/basket/updatebasketitem).
Here is an example:
```json
{
"PartNo": "TestPartNo",
"Quantity": 1.000,
"Comment": "This is an insert of locked price list to a new row in the basket",
"PriceListId": 15320,
"PriceListLocked": true
}
```
Then the returned basket item looks like this (shortened):
```json
{
"LineNo": 1,
"PartNo": "TestPartNo",
"PriceDisplay": 6000.00,
"Price": 0.00,
"PriceOriginal": 6000.00,
"Quantity": 1.000,
"PriceListId": 15320,
"PriceStandard": 5900.00,
"PriceDisplayIncVat": 7500.00,
"PriceListLocked": true
}
```
Note that the `PriceStandard` amount might be lower than the current `PriceDisplay` here, since this is a locked price.
`PriceListLocked` might return to false if
- You call an update to the shoppingservice, or
- The price list is no longer active on the product
### Additional isEditable and isBuyable logic
Some clients want to have more restrictions on what the basket than Norce provides, this could foe example be when a
basket is buyable and not. This could be a validation on products that they should be in-stock for example. Or even more
complex logic than that.
```csharp
public bool Buyable(Basket basket)
{
if (basket.isBuyable)
{
//Check my custom logic as well (for example, that all products are in stock)
return true;
} else
return false;
}
```
### Streamline basket processes
Event though Norce Commerce is flexible, some client solutions could benefit from a simplified view that is tailored to
their needs.
Examples:
- Add item with RecommendedQuantity set
- Add an already existing item as +1 to quantity
- Handle certain flagged products differently
- Handle overrides of prices as manual prices
### Extend the basket model
Many cases the client has need of extending the basket model adding properties as info types in Norce Commerce Shopping
Service. A common practice is to map these additional field to an extension to your basket model, so make it easier to
use.
## Promotions
Baskets apply promotions automatically if the requirements are valid. This means that prices or new items can suddenly
be shown in a basket depending on the effects. All applied promotions are listed in the `AppliedPromotions` list on
the basket and on the basket item as well.
Some promotions are applied using a code. Use `UpdateBasket` and set the `DiscountCode` property to enable these kind of
promotions. If no such promotion exists or if it isn't valid, the basket will simply not show a discount code after
update.
See a Postman
example [here](https://documenter.getpostman.com/view/2973406/2sA35MzK14#91bf4fcb-48da-4fd3-8399-4db8291f6957).
## Complex items
Norce Commerce allowes for more complex items to be added to the basket. By that we mean items containing other items.
Use the `ParentLineNo` to display these items in an appropriate manner in the UI.
To simplify handling of these items there are some additional methods:
- [InsertBasketItemWithChildren](/api-reference/services/shoppingservice/openapi/basket/insertbasketitemwithchildren),
takes a list of Basketitems to insert. The first is the parent.
- [UpdateBasketItemQuantityWithChildren](/api-reference/services/shoppingservice/openapi/basket/updatebasketitemquantitywithchildren),
lets you change the quantity of the parent and will also calculate the quantity change on its children.
Examples of items that use this functionality is products of type `ManagedStructure`, `ManagedErpPackage` and
`ManagedErpPackageWithCalc` and their Unmanaged counterparts.
## Samples in Postman
We have some good samples on how to work with
baskets [here](https://documenter.getpostman.com/view/2973406/2sA35MzK14#d8eb437c-32b1-4dc3-a867-1bab2f923d2d).
## Suggested further reading
- [Checkout process](/developer-portal/app-development/working-with-the-checkout-process)