Edara API v3: Stock Items
Read the guide first: authentication, paging, errors, rate limits and the shared PagedResult, BatchResult and *Reference shapes.
GET /v3/stock-items: Lists stock items.POST /v3/stock-items/list: Lists stock items by filters.GET /v3/stock-items/{id}: Gets a stock item by id.GET /v3/stock-items/search: Searches stock items.POST /v3/stock-items: Creates a stock item.POST /v3/stock-items/batch: Creates stock items in batch.PUT /v3/stock-items/{id}: Updates a stock item by id.PUT /v3/stock-items/code/{code}: Updates a stock item by code.PUT /v3/stock-items/external-id: Updates a stock item external id.PUT /v3/stock-items/batch/by-id: Batch updates stock items by id.PUT /v3/stock-items/batch/by-code: Batch updates stock items by code.PUT /v3/stock-items/batch/by-sku: Batch updates stock items by SKU.DELETE /v3/stock-items/{id}: Deletes a stock item by id.PUT /v3/stock-items/{id}/deactivate: Deactivates a stock item by id.PUT /v3/stock-items/code/{code}/deactivate: Deactivates a stock item by code.POST /v3/stock-items/link-to-parent: Links a stock item to a parent.GET /v3/stock-items/{stockItemId}/validate/serial/{serialNo}/returns/{customerId}: Validates an item serial for return.GET /v3/stock-items/{stockItemId}/validate/serial/{serialNo}/returned/{rrCode}: Validates an item serial returned.GET /v3/stock-items/balances: Lists stock item balances.GET /v3/stock-items/warehouse-summary: Gets stock item sales and stock position by warehouse.GET /v3/stock-items/{stockItemId}/balance: Gets a stock item balance.GET /v3/stock-items/{stockItemId}/balance/warehouses/{warehouseId}: Gets a stock item balance by warehouse.GET /v3/stock-items/{stockItemId}/cost: Gets a stock item cost.GET /v3/stock-items/cost/by-skus: Gets stock item costs by SKUs.GET /v3/stock-items/cost/by-part-numbers: Gets stock item costs by part numbers.GET /v3/stock-items/cost/by-ids: Gets stock item costs by ids.GET /v3/stock-items/{stockItemId}/global-balance: Gets a stock item global balance by id.GET /v3/stock-items/global-balances: Gets a stock item global balance.
Endpoints
GET /v3/stock-items: Lists stock items.
Operation GetStockItems · permission read:stock-item
Query string: GetStockItemsQuery
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400) | Maximum number of items to return. Defaults to 100, maximum 1000. |
ids |
List<int> |
new List |
each: GreaterThan(0) | Optional stock-item identifier filter. |
codes |
List<string> |
new List |
each: Must(code => !string.IsNullOrWhiteSpace(code)) | Optional codes filter. |
partNumbers |
List<string> |
new List |
each: Must(partNumber => !string.IsNullOrWhiteSpace(partNumber)) | Optional part-numbers filter. |
externalIds |
List<string> |
new List |
each: Must(externalId => !string.IsNullOrWhiteSpace(externalId)) | Optional external-ids filter. |
description |
string |
MaximumLength(500) .Must(description => !string.IsNullOrWhiteSpace(description)) .When(x => x.Description != null) | Optional description contains filter. | |
code |
string |
MaximumLength(200) .Must(code => !string.IsNullOrWhiteSpace(code)) .When(x => x.Code != null) | Optional exact-code filter. | |
sku |
string |
MaximumLength(50) .Must(sku => !string.IsNullOrWhiteSpace(sku)) .When(x => x.Sku != null) | Optional SKU filter. | |
partNumber |
string |
MaximumLength(500) .Must(partNumber => !string.IsNullOrWhiteSpace(partNumber)) .When(x => x.PartNumber != null) | Optional part-number filter. | |
externalId |
string |
MaximumLength(128) .Must(externalId => !string.IsNullOrWhiteSpace(externalId)) .When(x => x.ExternalId != null) | Optional exact external-id filter. | |
classificationId |
int? |
GreaterThan(0) .When(x => x.ClassificationId.HasValue) | Optional classification identifier filter. | |
updateDate |
DateTime? |
Updated-after filter. |
Responses: OK PagedResult<StockItemResponse>: Paged list of stock items.
Notes
- Only one filter is applied per request. The first one present in this order wins, and any later one is ignored without an error:
code,sku,partNumber,externalId,classificationId,codes,partNumbers,ids,externalIds. code,partNumberandexternalIdare exact matches, not partial ones.skuis an exact match that ignores case and returns at most one item.- When one of these filters finds nothing, you get
200with an emptyitemsandtotalCount0, not404. - A
codelookup always applies your user's item data permissions, even when the organization has not turned them on for stock items. An item your user is not permitted to see comes back as an empty result. codes,partNumbers,idsandexternalIdsare exact matches. Values are trimmed, duplicates are removed ignoring case, and unknown values are skipped without an error.- These list filters also return inactive items and grouping items.
classificationIdreturns only items directly in that classification, not items in its child classifications. Inactive items and grouping items are included.- With any of these filters,
offsetandlimitare ignored and every match comes back in one response.totalCountis the number of matches, andpageandpageSizeonly repeat your request. - With none of these filters, or with only
descriptionorupdateDate, you get the default list. It is paged, ordered by id, andtotalCountis the full number of matches. - The default list never includes grouping items, but it does include inactive items.
descriptionis a partial match (contains).updateDatereturns items created or updated strictly after that time.skuandpartNumbernever work as partial-match filters on this endpoint.- The default list applies item data permissions only when the organization has turned them on. With them on, a user with no permitted items gets
404. - The default list returns
404when nothing matches, unlike the filters above, which return200with an emptyitems. Handle both. - Only the first 100 characters of
descriptionare used for matching, although longer values are accepted. childItemsis filled only for grouping items, and the units of measure list only for items that have a unit of measure chain.code,sku,partNumberandexternalIdcan be null in the response.- Results from the filters above have no guaranteed order.
POST /v3/stock-items/list: Lists stock items by filters.
Operation GetStockItemsByFilters · permission read:stock-item
Body: StockItemFiltersRequest
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400) | Maximum number of items to return. Defaults to 100, maximum 1000. |
description |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)) .When(x => x.Description != null) | Description text to match. | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)) .When(x => x.Sku != null) | SKU to match. | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)) .When(x => x.PartNumber != null) | Part number to match. | |
ids |
List<int> |
new List |
each: GreaterThan(0) | Stock-item identifiers to resolve. |
Responses: OK PagedResult<StockItemResponse>: Paged list of stock items.
Notes
- Results are ordered by id and paged with
offsetandlimit.totalCountis the full number of matches. - An
offsetpast the last item returnstotalCount0, not the real total. description,skuandpartNumberare partial matches (contains), andidsis an exact list. All the filters you send must match together, and an emptyidslist means no id filter.- Inactive items are returned. Grouping items are not, and neither are items with no value for the grouping flag.
- Only the first 100 characters of
descriptionandpartNumberare used for matching, although longer values are accepted. - A filter that contains only spaces returns
400, and so does an id of 0 or less. - Item data permissions are applied unless the organization has explicitly turned them off for stock items.
- No match returns
200with an emptyitems, never404.
GET /v3/stock-items/{id}: Gets a stock item by id.
Operation GetStockItemById · permission read:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The stock item id. |
Responses: OK StockItemResponse: The stock item.
Notes
- Inactive items and grouping items are returned.
- The item picture is never included in the response.
- The global opening balance is the sum of the item's opening balances across all warehouses.
childItemsis filled only for grouping items, and the units of measure list only for items that have a unit of measure chain.
GET /v3/stock-items/search: Searches stock items.
Operation SearchStockItems · permission read:stock-item
- Separator selects the match mode: comma (
a,b,c) is OR (default), plus (a+b) is AND (every token must match),*is wildcard (returns the full active list).- Tokens are matched against the search fields enabled by tenant settings:
AllowSearchStockItemsByPartNumber,AllowSearchStockItemsByItemCode,AllowSearchStockItemsByClassificationCode,AllowSearchStockItemsByDescription,AllowSearchStockItemsBySKU,AllowSearchStockItemsByOENumber.- Returns the full matched set (no paging). Inactive items are excluded.
- Example:
keywords=screwdriver,hammerreturns items matching either token.
Query string: SearchStockItemsQuery
| field | type | default | validation | description |
|---|---|---|---|---|
keywords |
string |
NotEmpty() | Tokenized expression: , = OR, + = AND, * = all. Example: screwdriver,hammer. |
Responses: OK IReadOnlyCollection<StockItemResponse>: Matched stock items.
Notes
- At most 1000 items are returned. There is no paging and no
totalCount, so you cannot tell a cut-off result from a complete one. - Results are sorted by classification code, then description. When more than 1000 items match, which 1000 you get is not defined.
- The whole
keywordsvalue, trimmed and not split, is first tried as an exact part number. If any item matches, only those items are returned and no keyword search runs. - Next, by default, the keywords are matched against unit of measure part numbers only, and the other fields are searched only if that finds nothing. Two organization settings control this step, so it can differ between organizations.
- If
keywordscontains a plus sign, it is split on plus signs and every part must match. Otherwise it is split on commas and any part can match. - When
keywordshas both, only the plus signs split it. For example, a+b,c gives the parts a and b,c. - A
keywordsvalue of exactly one asterisk skips matching and returns up to 1000 items. - Each part is matched against the fields the organization has enabled for search, out of classification code, part number, SKU, OE number, code and description. A part matches when any enabled field matches.
- Each field is a partial match by default, and an organization setting can make it an exact match. These settings change what is searched, not which fields are returned, so code defensively.
- Inactive items and grouping items are never returned.
- Blank
keywordsis rejected with a validation error. No match returns200with an empty array, never404. - If the organization has turned off search on classification code, part number, SKU, code and description, the search returns nothing, even when OE number is enabled.
POST /v3/stock-items: Creates a stock item.
Operation CreateStockItem · permission create:stock-item
- IsCurrent on each
ChildItemsentry is ignored on create: it only applies to Update calls that transform a simple item into a grouping item.
Body: CreateStockItemRequest
| field | type | default | validation | description |
|---|---|---|---|---|
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. Required. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item. | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost; this is copied into the current average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost; this is copied into the current FIFO valuation. | ||
openingLifo |
decimal? |
The opening LIFO cost; this is copied into the current LIFO valuation. | ||
openingLastCost |
decimal? |
The opening last cost; this is copied into the current last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: Created StockItemResponse: Stock item created.
Business errors (HTTP 409, match on errorCode):
CannotAssignInactiveTax: An inactive tax cannot be assigned.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.StockitemsClassificationCannotBeNull: A classification must be assigned to the stock item.TaxNotFound: The specified tax was not found.
Notes
- Only
descriptionis always required. Depending on organization settings,code,sku,partNumber,brandIdandsalesPricecan be required too, so a request that works in one organization can fail in another. - A missing value that the organization requires gives
409withStockItemCodeRequired,StockItemSKURequired,StockItemPartNumberRequired,StockItemBrandRequiredorStockItemSalesPriceMustBeGreaterThanZero.codeis only required when the organization does not generate codes automatically. - When the organization requires a sales price, a
salesPricethat fails the check can also be rejected with a plain400before the409check runs. Handle both. - Uniqueness also depends on organization settings. Where the organization enforces it, a duplicate
code,description,partNumberorskugives409withStockItemCodeExists,StockItemDescriptionExists,StockItemPartNumberExistsorDupplicatedSKU. - The part number check also covers every
uomPartNumberinstockItemUnitOfMeasures.externalIdand barcodes are not checked for duplicates. - If you omit
classificationId, the organization's default classification is used when one is configured. Otherwise you get409StockitemsClassificationCannotBeNull. brandId,classificationIdandparentItemIdare not checked for existence. An id that does not exist gives500instead of a business error, so check these ids before you send them.- Send
singleUomIdorunitOfMeasureChainId, not both. Both gives400. With neither, the organization's default single unit is used andstockItemUnitOfMeasuresis ignored. taxIdandwithholdingTaxIdmust point to an existing, active tax that is not scoped to service items and has a sales or purchase account. Otherwise you get409withTaxNotFound,CannotAssignInactiveTax,InvalidTaxScopeForItemorInvalidTaxTypeForItem.- When the organization is connected to e-invoicing or e-receipts,
taxIdis required. A missing one gives409MustSelectValidTaxType. - The tax rate and withholding tax rate are copied onto the item when it is created.
- A negative opening cost gives
409InvalidOpeningCostValue. - On create,
averageCost,fifo,lifoandlastCostin the request are ignored. They are set from the four opening cost fields. - Unless the organization allows special characters in item descriptions, a
descriptionthat contains a double quote, single quote, pipe, backslash, comma, less-than sign or greater-than sign gives400. - The
409codesCodeContainsInvalidSpecialCharacters,DescriptionContainsInvalidSpecialCharactersandOtherLangDescriptionContainsInvalidSpecialCharactersare listed for this endpoint but are not returned. The special character check gives400. - For a grouping item (
isGroupingItemset to true),dynamicPropertiesInfois only accepted when the organization has dynamic properties enabled for stock items. Otherwise you get400. - Every
dynamicValueIdmust exist and belong to thedynamicPropertyIdyou state. Names you send are replaced with the stored ones. - A grouping item needs at least one entry in
childItems. Each child needs one value for every parent property, and no two children can have the same combination. - One stock item is created per
childItemsentry, using that entry's code, part number, SKU and price. Each child must pass the same required and uniqueness rules. A child'scodeis cleared when the organization generates codes automatically, and children are created without anexternalId. - Tags in
tagsthat do not exist yet are added to the organization's tag list. - The create is all or nothing. If any part fails, including a unit of measure, a dynamic property, a child item or a tag, nothing is saved.
POST /v3/stock-items/batch: Creates stock items in batch.
Operation BatchInsertStockItems · permission create:stock-item
Body: List<CreateStockItemRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. Required. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item. | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost; this is copied into the current average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost; this is copied into the current FIFO valuation. | ||
openingLifo |
decimal? |
The opening LIFO cost; this is copied into the current LIFO valuation. | ||
openingLastCost |
decimal? |
The opening last cost; this is copied into the current last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemBatchResult: Batch insert result.
Business errors (HTTP 409, match on errorCode):
CannotAssignInactiveTax: An inactive tax cannot be assigned.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.StockitemsClassificationCannotBeNull: A classification must be assigned to the stock item.TaxNotFound: The specified tax was not found.
Notes
- The response is always
200, with asucceededlist and afailedmap of key to reason. Each item is saved on its own, so items that succeeded stay saved when a later item fails. - Each
failedreason is plain text, not a structured error. A business rule failure reads "Bad Request." followed by theerrorCodeand the message. Unexpected failures start with "Internal Server Error." - The whole request is rejected with
400only when the list is empty or has more than 1000 items. failedis keyed bydescription, or by an empty string when it is missing. Two failed items with the same description overwrite each other.- After an item fails, later items in the batch with the same
descriptionare skipped and appear in neither list. Make descriptions unique within a batch. - Entries in
succeededare not read back after saving, so values that the server fills in can be missing. Read the item again if you need them.
PUT /v3/stock-items/{id}: Updates a stock item by id.
Operation UpdateStockItem · permission update:stock-item
- When transforming a simple item into a grouping item (
existing.IsGroupingItem = false,request.IsGroupingItem = true), exactly one entry inChildItemsmust set IsCurrent = true to mark the carry-over of the original simple item. On Updates of already-grouping items,IsCurrentis ignored.
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The stock item id. |
Body (sparse PUT: omitted fields keep their value): UpdateStockItemRequest
| field | type | default | validation | description |
|---|---|---|---|---|
imageUrlProvided |
bool |
True when the request body explicitly included ImageUrl. Set by FromBodySparseAttribute; never bound from client JSON. Internal-connector callers that omit ImageUrl keep the stock item's existing image instead of having it nulled out (sparse-PUT semantics). |
||
id |
int? |
Stock-item identifier. Optional on single-update; required on batch by-id update. | ||
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item (replaces any existing tags). | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost. | ||
openingLifo |
decimal? |
The opening LIFO cost. | ||
openingLastCost |
decimal? |
The opening last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
allowForSMS |
bool? |
Whether the item is permitted on outbound SMS notifications. Update-only. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemResponse: The updated stock item.
Business errors (HTTP 409, match on errorCode):
BatchNumberCannotChangeInUse: The batch-number setting cannot be changed because the item is already used in transactions.CannotAssignInactiveTax: An inactive tax cannot be assigned.ChangingStockItemUOMnotAllowedAlreadyIntransactions: The unit of measure cannot change because the item is already used in transactions.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.EnforceExpirationDateEntryCannotChangeInUse: The expiration-date-entry flag cannot be changed because the item is already used in transactions.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.PhantomRead: The stock item was modified by another user; reload and retry.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.TaxNotFound: The specified tax was not found.
Notes
- This is a full replace, not a partial update. Every field you omit is overwritten: text, ids,
tags,externalIdandimageUrlare cleared, true or false flags become false, and prices become 0. - Always send the whole item: read it with GET, change what you need, then PUT it back.
- Only these are kept when you omit them: the eight cost fields (the four opening costs,
averageCost,fifo,lifoandlastCost),code, and the unit setup when you omit bothsingleUomIdandunitOfMeasureChainId. - If you omit
imageUrl, the item's image is removed. Send the currentimageUrlto keep it. - An empty, null or malformed body gives
400with the message "The request body is required." - The unit chain and
stockItemUnitOfMeasuresare replaced on every update. SendingunitOfMeasureChainIdwithoutstockItemUnitOfMeasuresleaves the item with no unit rows. - Changing the unit chain of an item that is already used in transactions gives
409ChangingStockItemUOMnotAllowedAlreadyIntransactions. Sending bothsingleUomIdandunitOfMeasureChainIdgives400. - Because omitted flags become false, leaving out
enforceBatchNumberDateEntryorenforceExpirationDateEntryon an item that has them on and is in use gives409BatchNumberCannotChangeInUseorEnforceExpirationDateEntryCannotChangeInUse. This applies in organizations that use batch numbers. - Because an omitted
salesPricebecomes 0, the update fails with400or409StockItemSalesPriceMustBeGreaterThanZerowhen the organization requires a sales price. - The required, uniqueness and tax rules of POST /v3/stock-items apply here too. The item is not compared with itself in the uniqueness checks.
- An omitted
classificationIdis not replaced by the organization default on update. The classification is cleared. - You can get these
409codes although they are not in the documented list:PreventModifyOpeningCostAfterClosingJEwhen an opening cost changes after a closing journal entry exists,InvalidOpeningCostValuefor a negative opening cost, andDynamicPropertyValueCannotDeleteHasDependentDatawhen you remove a dynamic property value whose child items are in use. PhantomReadis only returned when the item is deleted while your request is running.- To turn a simple item into a grouping item, send
isGroupingItemas true withdynamicPropertiesInfoand at least one entry inchildItems, exactly one of them withisCurrentset to true. - In that change, the item you update becomes the current child, not the parent. It takes that child's code, part number, SKU and price. A new parent item is created with the old description, part number and SKU, and the other children are created under it.
- The response is the item with the
idyou sent, which is now a child withparentItemIdset. UseparentItemIdto find the new parent. - On an item that is already a grouping item, removing a value from
dynamicPropertiesInfodeletes the child items that use it. Adding a value requires at least onechildItemsentry that uses it, and the new children are created. dynamicPropertiesInfois only accepted when the organization has dynamic properties enabled for stock items. Otherwise you get400.- Tags in
tagsthat do not exist yet are added to the organization's tag list, and the tax rates are copied onto the item again.
PUT /v3/stock-items/code/{code}: Updates a stock item by code.
Operation UpdateStockItemByCode · permission update:stock-item
- When transforming a simple item into a grouping item (
existing.IsGroupingItem = false,request.IsGroupingItem = true), exactly one entry inChildItemsmust set IsCurrent = true to mark the carry-over of the original simple item. On Updates of already-grouping items,IsCurrentis ignored.
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
code |
route | string |
The stock item code. |
Body (sparse PUT: omitted fields keep their value): UpdateStockItemRequest
| field | type | default | validation | description |
|---|---|---|---|---|
imageUrlProvided |
bool |
True when the request body explicitly included ImageUrl. Set by FromBodySparseAttribute; never bound from client JSON. Internal-connector callers that omit ImageUrl keep the stock item's existing image instead of having it nulled out (sparse-PUT semantics). |
||
id |
int? |
Stock-item identifier. Optional on single-update; required on batch by-id update. | ||
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item (replaces any existing tags). | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost. | ||
openingLifo |
decimal? |
The opening LIFO cost. | ||
openingLastCost |
decimal? |
The opening last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
allowForSMS |
bool? |
Whether the item is permitted on outbound SMS notifications. Update-only. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemResponse: The updated stock item.
Business errors (HTTP 409, match on errorCode):
BatchNumberCannotChangeInUse: The batch-number setting cannot be changed because the item is already used in transactions.CannotAssignInactiveTax: An inactive tax cannot be assigned.ChangingStockItemUOMnotAllowedAlreadyIntransactions: The unit of measure cannot change because the item is already used in transactions.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.EnforceExpirationDateEntryCannotChangeInUse: The expiration-date-entry flag cannot be changed because the item is already used in transactions.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.PhantomRead: The stock item was modified by another user; reload and retry.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.TaxNotFound: The specified tax was not found.
Notes
- Works like PUT /v3/stock-items/{id}: full replace, the same kept fields, the same grouping, unit and
imageUrlrules, and the same errors. Only the way the item is found differs. - The
codein the path is trimmed and must match exactly. Partial matches are not supported, and a blank code gives400. - Only items your user has data permission for are found. If the item exists but your user has no data permission for it you get
403. If it does not exist you get404. - If you omit
codein the body, the item keeps the code from the path. A differentcodein the body renames the item. - After a rename the response is
200with a null body, even though the update was saved. Read the item again by its new code.
PUT /v3/stock-items/external-id: Updates a stock item external id.
Operation UpdateStockItemExternalId · permission update:stock-item
Body: UpdateStockItemExternalIdRequest
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
NotNull().GreaterThan(0) | Stock-item identifier. Required. | |
externalId |
string |
MaximumLength(128) | New external identifier; null/empty to clear. |
Responses: OK StockItemResponse: The updated stock item.
Business errors (HTTP 409, match on errorCode):
PhantomRead: The stock item was modified by another user; reload and retry.
Notes
- Changes only
externalId. Nothing else on the item is touched, and the full replace rules of PUT /v3/stock-items/{id} do not apply. - A blank or whitespace-only
externalIdclears the external id. externalIdis not checked for uniqueness. Several items can end up with the same value, and you do not get a409for it.- An
idthat does not exist gives404.PhantomRead(409) is only returned when the item is deleted while your request is running.
PUT /v3/stock-items/batch/by-id: Batch updates stock items by id.
Operation BatchUpdateStockItemsById · permission update:stock-item
Body (sparse PUT: omitted fields keep their value): List<UpdateStockItemRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
imageUrlProvided |
bool |
True when the request body explicitly included ImageUrl. Set by FromBodySparseAttribute; never bound from client JSON. Internal-connector callers that omit ImageUrl keep the stock item's existing image instead of having it nulled out (sparse-PUT semantics). |
||
id |
int? |
Stock-item identifier. Optional on single-update; required on batch by-id update. | ||
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item (replaces any existing tags). | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost. | ||
openingLifo |
decimal? |
The opening LIFO cost. | ||
openingLastCost |
decimal? |
The opening last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
allowForSMS |
bool? |
Whether the item is permitted on outbound SMS notifications. Update-only. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemBatchResult: Batch update result.
Business errors (HTTP 409, match on errorCode):
BatchNumberCannotChangeInUse: The batch-number setting cannot be changed because the item is already used in transactions.CannotAssignInactiveTax: An inactive tax cannot be assigned.ChangingStockItemUOMnotAllowedAlreadyIntransactions: The unit of measure cannot change because the item is already used in transactions.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.EnforceExpirationDateEntryCannotChangeInUse: The expiration-date-entry flag cannot be changed because the item is already used in transactions.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.PhantomRead: The stock item was modified by another user; reload and retry.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.TaxNotFound: The specified tax was not found.
Notes
- Each item is a full replace, as in PUT /v3/stock-items/{id}. Omitted fields are cleared, set to false or set to 0, except the cost fields and the unit setup. The grouping rules also apply.
- An omitted
imageUrlremoves the item's image. - The response is always
200withsucceededandfailed. Each item is saved on its own, and nothing is rolled back when another item fails. - The whole request is rejected with
400only when the list is empty or has more than 1000 items. Failure reasons are plain text, as in POST /v3/stock-items/batch. failedis keyed by the item'sdescription, or by "Item ID" followed by the id when the description is missing. Failed items with the same description overwrite each other.- An item with a missing or unknown
idfails with the reason "A StockItem with the specified ID was not found." - An omitted
codeis not kept here, unlike the single update. The item's code is blanked, or the item fails withStockItemCodeRequiredwhen the organization requires codes. Always sendcode. - Entries in
succeededare not read back after saving. Read the item again if you need the stored values.
PUT /v3/stock-items/batch/by-code: Batch updates stock items by code.
Operation BatchUpdateStockItemsByCode · permission update:stock-item
Body (sparse PUT: omitted fields keep their value): List<UpdateStockItemRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
imageUrlProvided |
bool |
True when the request body explicitly included ImageUrl. Set by FromBodySparseAttribute; never bound from client JSON. Internal-connector callers that omit ImageUrl keep the stock item's existing image instead of having it nulled out (sparse-PUT semantics). |
||
id |
int? |
Stock-item identifier. Optional on single-update; required on batch by-id update. | ||
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item (replaces any existing tags). | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost. | ||
openingLifo |
decimal? |
The opening LIFO cost. | ||
openingLastCost |
decimal? |
The opening last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
allowForSMS |
bool? |
Whether the item is permitted on outbound SMS notifications. Update-only. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemBatchResult: Batch update result.
Business errors (HTTP 409, match on errorCode):
BatchNumberCannotChangeInUse: The batch-number setting cannot be changed because the item is already used in transactions.CannotAssignInactiveTax: An inactive tax cannot be assigned.ChangingStockItemUOMnotAllowedAlreadyIntransactions: The unit of measure cannot change because the item is already used in transactions.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.EnforceExpirationDateEntryCannotChangeInUse: The expiration-date-entry flag cannot be changed because the item is already used in transactions.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.PhantomRead: The stock item was modified by another user; reload and retry.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.TaxNotFound: The specified tax was not found.
Notes
- The response works like PUT /v3/stock-items/batch/by-id: always
200withsucceededandfailed, each item saved on its own, and a whole-request400only for an empty list or more than 1000 items. - Each item is found by its trimmed
code, with an exact match, among the items your user has data permission for. An item outside your data permission is reported as not found. - An item with a blank or missing
codefails with the reason "A StockItem with the specified Code was not found." failedis keyed by the item'sdescription, or by an empty string when it is missing, so all failures without a description collapse into one entry.- Grouping is not handled here. Child items and parent dynamic properties in the request are ignored, and the item is updated as a simple item.
- An
idin the body is ignored. The item updated is always the one found bycode. - Each item is otherwise a full replace, as in PUT /v3/stock-items/{id}: omitted fields are cleared, set to false or set to 0, with the same rule for keeping the unit setup. Because
codeis the lookup key, it is never blanked here.
PUT /v3/stock-items/batch/by-sku: Batch updates stock items by SKU.
Operation BatchUpdateStockItemsBySKU · permission update:stock-item
Body (sparse PUT: omitted fields keep their value): List<UpdateStockItemRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
imageUrlProvided |
bool |
True when the request body explicitly included ImageUrl. Set by FromBodySparseAttribute; never bound from client JSON. Internal-connector callers that omit ImageUrl keep the stock item's existing image instead of having it nulled out (sparse-PUT semantics). |
||
id |
int? |
Stock-item identifier. Optional on single-update; required on batch by-id update. | ||
code |
string |
MaximumLength(200) .Must(c => !string.IsNullOrWhiteSpace(c)).When(x => x.Code != null) | The stock-item code (unique per tenant). | |
description |
string |
NotEmpty().MaximumLength(500) | The stock-item description. | |
otherLanguageDescription |
string |
MaximumLength(500) .Must(d => !string.IsNullOrWhiteSpace(d)).When(x => x.OtherLanguageDescription != null) | The description in the secondary language (e.g. Arabic). | |
sku |
string |
MaximumLength(50) .Must(s => !string.IsNullOrWhiteSpace(s)).When(x => x.Sku != null) | The stock-keeping unit identifier (unique per tenant when supplied). | |
partNumber |
string |
MaximumLength(500) .Must(p => !string.IsNullOrWhiteSpace(p)).When(x => x.PartNumber != null) | The manufacturer or vendor part number. | |
oENumber |
string |
MaximumLength(200) | The OEM (original equipment manufacturer) number. | |
externalId |
string |
MaximumLength(128) .Must(e => !string.IsNullOrWhiteSpace(e)).When(x => x.ExternalId != null) | An external identifier supplied by the caller for reconciliation. | |
classificationId |
int? |
GreaterThan(0).When(x => x.ClassificationId.HasValue) | The id of the classification node this item belongs to. | |
brandId |
int? |
GreaterThan(0).When(x => x.BrandId.HasValue) | The id of the brand. | |
parentItemId |
int? |
GreaterThan(0).When(x => x.ParentItemId.HasValue) | The id of the parent item, when this item is a variant. | |
isGroupingItem |
bool? |
Whether this item is a grouping (parent) item with variants underneath. | ||
tags |
string[] |
Must(tags => tags == null || tags.All(tag => !string.IsNullOrWhiteSpace(tag))) .Must(tags => tags == null || string.Join(",", tags).Length <= 4000) | The tags to assign to the item (replaces any existing tags). | |
singleUomId |
int? |
GreaterThan(0).When(x => x.SingleUomId.HasValue) | The id of the single UOM when the item is not part of a UOM chain. | |
unitOfMeasureChainId |
int? |
GreaterThan(0).When(x => x.UnitOfMeasureChainId.HasValue) | The id of the UOM chain the item uses. | |
unitOfMeasure |
int? |
GreaterThan(0).When(x => x.UnitOfMeasure.HasValue) | The id of the resolved unit of measure for this item. | |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureRequest> |
each: SetValidator(new StockItemUnitOfMeasureRequestValidator()) | Per-UOM pricing and identifiers when the item uses a UOM chain. | |
weight |
decimal? |
The item weight. | ||
height |
decimal? |
The item height. | ||
width |
decimal? |
The item width. | ||
length |
decimal? |
The item length. | ||
warranty |
decimal? |
The warranty period (interpretation per tenant settings). | ||
validityPeriodInDays |
decimal? |
The validity period in days after which the item is treated as expired. | ||
itemLocation |
string |
MaximumLength(200) | The default storage location of the item within a warehouse. | |
imageUrl |
string |
MaximumLength(200) | The URL to the item image. | |
note |
string |
MaximumLength(500) | Free-form notes captured against the item. | |
datasheet |
string |
The URL or text of the item datasheet. | ||
attachedDocument |
string |
The URL of an attached document. | ||
salesPrice |
decimal? |
The default sales price. | ||
purchasePrice |
decimal? |
The default purchase price. | ||
dealerPrice |
decimal? |
The dealer price. | ||
superDealerPrice |
decimal? |
The super-dealer price. | ||
minimumPrice |
decimal? |
The minimum allowed sales price. | ||
referencePrice |
decimal? |
The reference price used in margin calculations. | ||
unitPrice |
decimal? |
The unit price; used by some legacy callers. | ||
openingAverageCost |
decimal? |
The opening average cost. | ||
openingFifo |
decimal? |
The opening FIFO cost. | ||
openingLifo |
decimal? |
The opening LIFO cost. | ||
openingLastCost |
decimal? |
The opening last cost. | ||
averageCost |
decimal? |
The current average cost. | ||
fifo |
decimal? |
The current FIFO valuation. | ||
lifo |
decimal? |
The current LIFO valuation. | ||
lastCost |
decimal? |
The current last cost. | ||
globalReorderingPoint |
decimal? |
The global reordering point across all warehouses. | ||
globalMinimumPoint |
decimal? |
The global minimum stock point across all warehouses. | ||
globalMaximumPoint |
decimal? |
The global maximum stock point across all warehouses. | ||
taxId |
int? |
GreaterThan(0).When(x => x.TaxId.HasValue) | The id of the default sales tax for this item. | |
withholdingTaxId |
int? |
GreaterThan(0).When(x => x.WithholdingTaxId.HasValue) | The id of the withholding tax for this item, when applicable. | |
eInvoiceCode |
string |
MaximumLength(50) | The e-invoice item code (used by Egypt/KSA e-invoicing). | |
eInvoiceCodeType |
string |
MaximumLength(50) | The e-invoice code type (e.g. GS1, EGS). | |
enforceSerialEntry |
bool? |
Whether issuing this item must capture serial numbers. | ||
enforceBatchNumberDateEntry |
bool? |
Whether issuing this item must capture a batch number and production date. | ||
enforceExpirationDateEntry |
bool? |
Whether issuing this item must capture an expiration date. | ||
autofillBatchNumber |
bool? |
Whether batch numbers should be auto-generated when not supplied. | ||
allowSerialDuplication |
bool? |
Whether the same serial number may appear on more than one document. | ||
allowForSMS |
bool? |
Whether the item is permitted on outbound SMS notifications. Update-only. | ||
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
||
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). | ||
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. | ||
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. | ||
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. | ||
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. | ||
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). | ||
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. | ||
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. | ||
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. | ||
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. | ||
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). | ||
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. | ||
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. | ||
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. | ||
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
The dynamic-property values to assign to the item. | ||
childItems |
List<StockItemChildRequest> |
The child variants of this item when it is a grouping item. |
Responses: OK StockItemBatchResult: Batch update result.
Business errors (HTTP 409, match on errorCode):
BatchNumberCannotChangeInUse: The batch-number setting cannot be changed because the item is already used in transactions.CannotAssignInactiveTax: An inactive tax cannot be assigned.ChangingStockItemUOMnotAllowedAlreadyIntransactions: The unit of measure cannot change because the item is already used in transactions.CodeContainsInvalidSpecialCharacters: The stock-item code contains invalid special characters.DescriptionContainsInvalidSpecialCharacters: The stock-item description contains invalid special characters.DupplicatedSKU: Another stock item already uses the same SKU.EnforceExpirationDateEntryCannotChangeInUse: The expiration-date-entry flag cannot be changed because the item is already used in transactions.InvalidTaxScopeForItem: The tax scope is not valid for this stock item.InvalidTaxTypeForItem: The tax type is not valid for this stock item.MustSelectValidTaxType: A valid tax type must be selected.OtherLangDescriptionContainsInvalidSpecialCharacters: The other-language description contains invalid special characters.PhantomRead: The stock item was modified by another user; reload and retry.StockItemBrandRequired: A brand must be assigned to the stock item.StockItemCodeExists: Another stock item already uses the same code.StockItemCodeRequired: The stock-item code is required.StockItemDescriptionExists: Another stock item already uses the same description.StockItemPartNumberExists: Another stock item already uses the same part number.StockItemPartNumberRequired: The stock-item part number is required.StockItemSalesPriceMustBeGreaterThanZero: The sales price must be greater than zero.StockItemSKURequired: The stock-item SKU is required.TaxNotFound: The specified tax was not found.
Notes
- Works like PUT /v3/stock-items/batch/by-code (same response,
failedkeyed bydescriptionor an empty string, no grouping handling), except each item is found by its trimmedsku. - The
skumatch is not case sensitive. If more than one item has that SKU, only one of them is updated. - An item with a blank
skufails with the reason "A StockItem with the specified SKU was not found." - An omitted
codeblanks the item's code, or the item fails withStockItemCodeRequiredwhen the organization requires codes. Always sendcode.
DELETE /v3/stock-items/{id}: Deletes a stock item by id.
Operation DeleteStockItemById · permission delete:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The stock item id. |
Responses: NoContent: (not declared; read from the method body)
Business errors (HTTP 409, match on errorCode):
ItemCannotDeleteItInUse: The stock item cannot be deleted because it is in use.ItemCannotDeleteItInUseInPhysicalCount: The stock item cannot be deleted because it is used in a physical count.ItemCannotDeleterelatedToSupplier: The stock item cannot be deleted because it is referenced by a supplier.PhantomRead: The stock item was modified by another user; reload and retry.
Notes
- The delete is permanent. The item is removed, not marked as deleted.
- An unknown
idgives404. - Deleting a grouping (parent) item also deletes its child items.
- An item that is referenced anywhere else, for example in a bundle, cannot be deleted and fails with
ItemCannotDeleteItInUse. An item used in a physical count fails withItemCannotDeleteItInUseInPhysicalCount. Nothing is deleted in either case. ItemCannotDeleterelatedToSupplieris listed for this endpoint but is not returned. An item linked to a supplier fails withItemCannotDeleteItInUse.- In rare cases the API returns
204although the item was not deleted. If the delete matters, check that the item is gone.
PUT /v3/stock-items/{id}/deactivate: Deactivates a stock item by id.
Operation DeactivateStockItemById · permission update:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The stock item id. |
Responses: NoContent: Stock item deactivated.
Notes
- Only this item is deactivated. There is no check for stock balance or open documents, and the child items of a grouping item stay active.
- An unknown
idgives404. - Deactivating an item that is already inactive returns
204. - A
204does not guarantee the change. Errors while deactivating are not reported, so read the item again if you need to be sure. - There is no v3 endpoint to reactivate a stock item, and the update endpoints cannot change the active state. Reactivate the item in the Edara application.
PUT /v3/stock-items/code/{code}/deactivate: Deactivates a stock item by code.
Operation DeactivateStockItemByCode · permission update:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
code |
route | string |
The stock item code. |
Responses: NoContent: Stock item deactivated.
Notes
- Works like PUT /v3/stock-items/{id}/deactivate: only the item is deactivated, a
204does not guarantee the change, and there is no reactivation endpoint. - The item is found by the trimmed
codein the path. A blank code gives400, an item your user has no data permission for gives403, and a code that does not exist gives404.
POST /v3/stock-items/link-to-parent: Links a stock item to a parent.
Operation LinkStockItemToParent · permission update:stock-item
Body: LinkStockItemToParentRequest
| field | type | default | validation | description |
|---|---|---|---|---|
childItemId |
int? |
NotNull() .GreaterThan(0) | Child stock-item identifier. | |
parentItemId |
int? |
NotNull() .GreaterThan(0) | Parent (grouping) stock-item identifier. | |
dynamicPropertiesValuesIds |
string |
NotEmpty(); Must(value => { var tokens = SplitTokens(value); return tokens.All(t => int.TryParse(t, out )); }) .When(x => !string.IsNullOrWhiteSpace(x.DynamicPropertiesValuesIds)); Must(value => { var tokens = SplitTokens(value); return tokens.Length == tokens.Distinct().Count(); }) .When(x => !string.IsNullOrWhiteSpace(x.DynamicPropertiesValuesIds) && SplitTokens(x.DynamicPropertiesValuesIds).All(t => int.TryParse(t, out ))); Must(value => SplitTokens(value).Length <= 3) .When(x => !string.IsNullOrWhiteSpace(x.DynamicPropertiesValuesIds)) | Comma-separated dynamic-property value identifiers (1-3 distinct positive integers) identifying the variant. |
Responses: NoContent: Stock item linked.
Business errors (HTTP 409, match on errorCode):
ChildItemEqualsParentItem: A stock item cannot be linked to itself.ChildItemNotEligibleForLink: The child stock item is not eligible to be linked (missing, inactive, already a grouping item, already linked to a parent, or already has dynamic-property values).ParentItemMustBeGroupingItem: The parent stock item must exist and be marked as a grouping item.ParentDynamicPropertiesInconsistent: The parent item has dynamic-property definitions but no existing children; this state is inconsistent.DynamicPropertyValuesInvalid: One or more dynamic-property value identifiers are invalid or do not belong to a property group.MultipleValuesForSameDynamicPropertyGroup: More than one value was supplied for the same dynamic-property group.DuplicateDynamicPropertyCombination: Another child of the same parent already uses this exact dynamic-property value combination.DynamicPropertyGroupsDoNotMatchExistingChildren: The dynamic-property groups supplied do not match the groups used by existing children of this parent.
Notes
dynamicPropertiesValuesIdsis a comma-separated string of numeric value ids, with no duplicates and at most 3 values.- If another link request for the same
childItemIdis still running, you get400with the message "This link request is already being processed by another user." - The child must exist, be active, not be a grouping item, and not already have a parent or dynamic property values. It cannot be its own parent.
- The parent must exist and be a grouping item. It does not have to be active.
- Every value id must be valid, with one value per property. The combination must not already be used by another child of the parent, and it must cover the same properties as the existing children.
- A parent that has dynamic properties but no children is rejected as inconsistent.
- Linking sets the child's parent and dynamic property values, and adds any values the parent does not have yet to the parent. The child's description, code and prices do not change.
GET /v3/stock-items/{stockItemId}/validate/serial/{serialNo}/returns/{customerId}: Validates an item serial for return.
Operation ValidateItemSerialForReturn · permission read:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. | |
serialNo |
route | string |
The serial number to validate. | |
customerId |
route | int? |
The customer id. |
Responses: OK bool: True when the serial is valid for return.
Notes
- The result is true only when the most recent movement of that serial for the item is an issue (
IO). The serial number must match exactly. - With
customerId, only that customer's movements are looked at before the most recent one is picked. A serial that was later issued to or returned by another customer can still come back true. - A
customerIdof 0 or less means any customer. - An invalid serial gives
200with false, never404. That covers an unknown stock item, an unknown serial, a serial that was never issued, and a serial whose latest movement is not an issue. The response body is a bare JSON boolean. - Only current documents are checked, not archived ones, and movements in all warehouses count.
- When two movements have the same date, which one counts as the most recent is not defined.
GET /v3/stock-items/{stockItemId}/validate/serial/{serialNo}/returned/{rrCode}: Validates an item serial returned.
Operation ValidateItemSerialReturned · permission read:stock-item
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. | |
serialNo |
route | string |
The serial number to validate. | |
rrCode |
route | string |
The return-receipt code. |
Responses: OK bool: True when the serial has been returned.
Notes
- The result is true only when the most recent matching movement of that serial for the item is a return receipt (
RR). The serial number must match exactly. - Without
rrCode, the check answers whether the serial is currently in a returned state. Any later movement, for example a new issue (IO), makes it false. - With
rrCode, only movements on the document with exactly that code are considered. The check then answers whether the serial was on that return document, whatever happened afterwards. - A blank
rrCodemeans no document filter.rrCodeandserialNoare trimmed. - No match gives
200with false, never404. That covers an unknown stock item, an unknown serial and a wrongrrCode. The response body is a bare JSON boolean. - Only current documents are checked, not archived ones. There is no customer or warehouse filter.
- When two movements have the same date, which one counts as the most recent is not defined.
GET /v3/stock-items/balances: Lists stock item balances.
Operation GetStockItemBalances · permission read:stock-item:balance
Query string: GetStockItemBalancesQuery
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400) | Maximum number of items to return. Defaults to 100, maximum 1000. |
stockItemId |
int? |
GreaterThan(0) .When(x => x.StockItemId.HasValue) | Optional stock-item identifier filter. | |
warehouseId |
int? |
GreaterThan(0) .When(x => x.WarehouseId.HasValue) | Optional warehouse identifier filter. |
Responses: OK PagedResult<StockItemBalanceResponse>: Paged list of stock item balances.
Notes
- Each row is one stock item in one warehouse for one batch.
stockItemIdandwarehouseIdare optional exact-match filters. - With neither filter, you page through every stock row of the organization, including rows with a zero balance.
- Rows are ordered by stock item and then warehouse. When an item has several batches in one warehouse, their rows can move between pages. Use a large
limitor filter bystockItemId. - An empty result gives
404with the message "No Data Found.", not an empty page. This happens for unknown ids, for no stock, and for anoffsetpast the end, so treat404as the end of the list when you page. - The response has the current balance only. There is no available quantity field.
- A missing reserved quantity comes back as 0 and a missing batch number as null. The balance by stock item endpoint returns an empty string for a missing batch, so handle both.
GET /v3/stock-items/warehouse-summary: Gets stock item sales and stock position by warehouse.
Operation GetStockItemWarehouseSummary · permission read:stock-item:balance
Query string: GetStockItemWarehouseSummaryQuery
| field | type | default | validation | description |
|---|---|---|---|---|
dateFrom |
DateTime |
NotEmpty() | Start of the sales/sales-return summary period. | |
dateTo |
DateTime |
NotEmpty(); GreaterThanOrEqualTo(x => x.DateFrom) .When(x => x.DateFrom != default(DateTime) && x.DateTo != default(DateTime)) | End of the sales/sales-return summary period. | |
warehouseId |
List<int> |
new List |
each: GreaterThan(0) | Optional warehouse identifiers filter. |
stockitemId |
int? |
GreaterThan(0) .When(x => x.StockitemId.HasValue) | Optional stock-item identifier filter. | |
excludeOtherParty |
bool |
When true, excludes Issue/Receive Other Party transactions from the sales summary. | ||
offset |
int? |
0 | GreaterThanOrEqualTo(0) .When(x => x.Offset.HasValue) | Number of stock items to skip before returning results. Defaults to 0. |
limit |
int? |
1000 | InclusiveBetween(1, GetStockItemWarehouseSummaryQuery.MaxLimit) .When(x => x.Limit.HasValue) | Maximum number of stock items to return. Defaults to 1000, maximum 1000. |
Responses: OK PagedResult<StockItemWarehouseSummaryResponse>: Paged list of stock item warehouse summaries.
Notes
- Paging is over stock items, not over warehouse rows. Items are ordered by id, and grouping (parent) items are never included.
limitdefaults to 1000 and accepts up to 5000, even where the parameter description says 1000. A higher value gives400.- Only stock items your user has data permission for are returned, unless the organization has turned off data permissions for stock items. Results can differ between users and organizations, so code defensively.
balanceandreservedare current totals across all batches. They are not as ofdateTo.salescounts issue work orders (IO) only andsalesReturncounts return receipts (RR) only, both converted for unit of measure.dateFromanddateToare both inclusive and apply to the work order date. AdateTowithout a time means the start of that day, so send the end of the day (for example 23:59:59.997) to include it.- With
excludeOtherPartyset to true, work orders that have an other party are left out ofsalesandsalesReturn. expectedReceivecomes from open purchase orders that are not cancelled: ordered quantity minus issued quantity. It is not converted for unit of measure.expectedTransferis the quantity of pending transfers into the warehouse, converted for unit of measure.- The date range does not apply to
expectedReceiveorexpectedTransfer. - For each item,
warehouseslists only the warehouses that hold a stock record for it.warehouseIdnarrows that list but does not remove items: an item with no matching stock record comes back with an emptywarehouseslist. - An unknown
stockitemIdgives200with emptyitemsand atotalCountof 0, not404.
GET /v3/stock-items/{stockItemId}/balance: Gets a stock item balance.
Operation GetStockItemBalanceByStockItemId · permission read:stock-item:balance
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. |
Responses: OK List<StockItemBalanceResponse>: Stock item balance. · NotFound ProblemDetails: No balance found for the specified stock item.
Notes
- The response is a plain JSON array with no paging envelope. You get one row per warehouse and batch, and rows with a zero balance are included.
- The balance is always the current one. There is no date parameter.
balanceis the on-hand quantity, andreservedBalanceis 0 when nothing is reserved.batchNumberis an empty string, never null, when the row has no batch.- There is no available quantity field. Calculate it yourself as
balanceminusreservedBalance. stockItemis always filled in, even when the item is inactive.- An unknown
stockItemId, or an item with no stock rows, returns404, not an empty array.
GET /v3/stock-items/{stockItemId}/balance/warehouses/{warehouseId}: Gets a stock item balance by warehouse.
Operation GetStockItemBalanceByWarehouse · permission read:stock-item:balance
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. | |
warehouseId |
route | int |
The warehouse id. |
Responses: OK List<StockItemBalanceResponse>: Stock item balance for the warehouse. · NotFound ProblemDetails: No balance found for the specified stock item and warehouse.
Notes
- The response is a JSON array with one row per batch in that warehouse, not a single object.
- The balance is always the current one, and there is no available quantity field.
- An unknown item, an unknown warehouse, and a pair with no stock row all return the same
404.
GET /v3/stock-items/{stockItemId}/cost: Gets a stock item cost.
Operation GetStockItemCost · permission read:stock-item:balance
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. |
Query string: GetStockItemCostQuery
| field | type | default | validation | description |
|---|---|---|---|---|
date |
DateTime? |
NotNull() | Cost date. |
Responses: OK decimal: Stock item cost. · NotFound ProblemDetails: No stock item with the specified identifier was found.
Notes
- The cost is always the average cost. The organization's cost evaluation setting is not applied.
- The value is the average cost on the item's latest work order movement at or before
date, not counting opening-balance movements. If there is none, you get the opening-balance cost. - A
datewithout a time means the start of that day, so that day's movements are left out. Send the end of the day to include them. - The cost is global across all warehouses and is in the organization's base currency. The response is a plain decimal number, not an object.
GET /v3/stock-items/cost/by-skus: Gets stock item costs by SKUs.
Operation GetStockItemCostsBySkus · permission read:stock-item:balance
- The SKU list cannot exceed 200 entries.
Query string: GetStockItemCostsBySkusQuery
| field | type | default | validation | description |
|---|---|---|---|---|
skus |
string |
Comma-separated stock-item SKUs (max 200). | ||
date |
DateTime? |
NotNull() | Cost evaluation date (on or before). | |
| (object rule) | RuleFor(x => x) .Custom((query, context) => { if (string.IsNullOrWhiteSpace(query?.Skus)) { return; } if (query.Skus.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Length > 200) { context.AddFailure("Skus", "Skus count cannot exceed 200."); } }) |
Responses: OK IReadOnlyCollection<StockItemCostResponse>: Stock item costs.
Notes
- Costs follow the same rules as the single stock item cost: always the average cost, as of the latest movement at or before
date. Adatewithout a time means the start of that day. - An empty
skusreturns404, not400. More than 200 SKUs returns400. - Unknown SKUs are left out of the response without an error, and you get
404only when none is found. Check the returned items against the list you sent.
GET /v3/stock-items/cost/by-part-numbers: Gets stock item costs by part numbers.
Operation GetStockItemCostsByPartNumbers · permission read:stock-item:balance
- The part-number list cannot exceed 200 entries.
Query string: GetStockItemCostsByPartNumbersQuery
| field | type | default | validation | description |
|---|---|---|---|---|
partNumbers |
string |
Comma-separated stock-item part numbers (max 200). | ||
date |
DateTime? |
NotNull() | Cost evaluation date (on or before). | |
| (object rule) | RuleFor(x => x) .Custom((query, context) => { if (string.IsNullOrWhiteSpace(query?.PartNumbers)) { return; } if (query.PartNumbers.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Length > 200) { context.AddFailure("PartNumbers", "Part numbers count cannot exceed 200."); } }) |
Responses: OK IReadOnlyCollection<StockItemCostResponse>: Stock item costs.
Notes
- Costs follow the same rules as the single stock item cost: always the average cost, as of the latest movement at or before
date. - An empty
partNumbersreturns404. Unknown part numbers are left out of the response without an error.
GET /v3/stock-items/cost/by-ids: Gets stock item costs by ids.
Operation GetStockItemCostsByIds · permission read:stock-item:balance
- The identifier list cannot exceed 100 entries.
Query string: GetStockItemCostsByIdsQuery
| field | type | default | validation | description |
|---|---|---|---|---|
ids |
string |
Comma-separated stock-item identifiers (max 100). | ||
date |
DateTime? |
NotNull() | Cost evaluation date (on or before). | |
| (object rule) | RuleFor(x => x) .Custom((query, context) => { if (string.IsNullOrWhiteSpace(query?.Ids)) { return; } if (query.Ids.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Length > 100) { context.AddFailure("Ids", "Ids count cannot exceed 100."); } }) |
Responses: OK IReadOnlyCollection<StockItemCostResponse>: Stock item costs.
Notes
- Costs follow the same rules as the single stock item cost: always the average cost, as of the latest movement at or before
date. - An empty
idsreturns404. Unknown ids are left out of the response without an error.
GET /v3/stock-items/{stockItemId}/global-balance: Gets a stock item global balance by id.
Operation GetStockItemGlobalBalanceById · permission read:stock-item:balance
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
stockItemId |
route | int |
The stock item id. |
Responses: OK StockItemGlobalBalanceResponse: Stock item global balance. · NotFound ProblemDetails: No stock item with the specified identifier was found.
Notes
- The response is a single object with
stockItem,globalBalanceandglobalReservedBalance. It has no per-warehouse or per-batch rows and no available quantity field. globalBalanceis the on-hand total across all warehouses plus the quantities of internal transfers that arePendingorRejected. While such a transfer is open, it does not equal the sum of the per-warehousebalancevalues.globalReservedBalanceis the reserved total across all warehouses, with no transfer adjustment. It is 0 when nothing is reserved.- Values are always current. There is no date parameter.
- An unknown id returns
404. A known item with no stock returns200with both values 0.
GET /v3/stock-items/global-balances: Gets a stock item global balance.
Operation GetStockItemGlobalBalance · permission read:stock-item:balance
- Supply either
codeorsku, but not both.
Query string: GetStockItemGlobalBalanceQuery
| field | type | default | validation | description |
|---|---|---|---|---|
code |
string |
Stock-item code. Mutually exclusive with Sku. |
||
sku |
string |
Stock-item SKU. Mutually exclusive with Code. |
Responses: OK decimal: Stock item global balance. · NotFound ProblemDetails: No stock item was found for the supplied code or SKU.
Notes
- The response is a plain decimal number, for example 42.0000, not an object. It is the global on-hand figure only, with no reserved figure and no stock item reference.
- Send exactly one of
codeorsku. Sending both, or neither, returns400. codeis trimmed and matched exactly. An item outside your stock item data permissions returns404, the same as an unknown code.skuis trimmed and matched exactly, ignoring case. An unknown SKU returns404.- If more than one item has the same
sku, one of them is picked without an error. - The value is the current on-hand total across all warehouses plus the quantities of internal transfers that are
PendingorRejected, the same asglobalBalance.
Types
BrandReference
Lightweight brand reference (id + name).
| field | type | description |
|---|---|---|
id |
int |
The brand id. |
name |
string |
The brand name. |
ClassificationReference
Lightweight stock-item classification reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The classification id. |
code |
string |
The classification code. |
name |
string |
The classification name. |
DynamicPropertyInfo
Dynamic-property value assignment for a grouping or child stock item.
| field | type | description |
|---|---|---|
dynamicPropertyId |
int |
Dynamic-property identifier (e.g. "Color"). |
dynamicProperty |
string |
Dynamic-property name; corrected from DB on write. |
dynamicValueId |
int |
Dynamic-property value identifier (e.g. "Red"). |
dynamicValue |
string |
Dynamic-property value text; corrected from DB on write. |
StockItemBalanceResponse
Response describing a stock-item balance row in a specific warehouse and (optional) batch.
| field | type | description |
|---|---|---|
warehouse |
WarehouseReference |
The warehouse the balance applies to. |
stockItem |
StockItemReference |
The stock item the balance applies to. |
balance |
decimal |
The available on-hand quantity in the primary UOM. |
reservedBalance |
decimal |
The quantity reserved against pending issues. |
batchNumber |
string |
The batch number, when the stock item is batch-tracked. |
productionDate |
DateTime? |
The batch production date, when applicable. |
expirationDate |
DateTime? |
The batch expiration date, when applicable. |
StockItemBatchResult
Response describing the result of a stock-item batch operation.
| field | type | description |
|---|---|---|
succeeded |
List<StockItemResponse> |
Successfully processed stock items. |
failed |
Dictionary<string,string> |
Failed items keyed by description with the failure reason. |
StockItemChildRequest
Request to create a child (variant) of a grouping stock item.
| field | type | description |
|---|---|---|
code |
string |
Child code. |
sku |
string |
Child SKU. |
price |
decimal? |
Child price. |
partNumber |
string |
Child part number. |
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
Dynamic-property value combination defining this variant. |
isCurrent |
bool? |
Marks this child as the carry-over of the existing item when an Update transforms a simple item into a grouping item. Exactly one child must set this in the transform case; ignored otherwise. |
StockItemChildResponse
Response describing a child stock item of a grouping item.
| field | type | description |
|---|---|---|
id |
int |
Child identifier. |
description |
string |
Description. |
code |
string |
Code. |
sku |
string |
SKU. |
price |
decimal |
Displayed price. |
partNumber |
string |
Part number. |
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
Dynamic-property assignments defining this variant. |
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). |
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. |
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. |
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. |
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. |
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). |
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. |
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. |
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. |
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. |
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). |
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. |
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. |
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. |
StockItemCostResponse
Response describing the current cost of a stock item.
| field | type | description |
|---|---|---|
stockItemId |
int |
The stock-item id. |
stockItemCode |
string |
The stock-item code. |
stockItemSku |
string |
The stock-item SKU. |
stockItemPartNumber |
string |
The stock-item part number. |
cost |
decimal |
The unit cost in the system currency. |
StockItemGlobalBalanceResponse
Response describing a stock item's global balance summary across all warehouses.
| field | type | description |
|---|---|---|
stockItem |
StockItemReference |
The stock item the balance applies to. |
globalBalance |
decimal |
The total on-hand quantity across all warehouses, in the primary UOM. |
globalReservedBalance |
decimal |
The total reserved quantity across all warehouses, in the primary UOM. |
StockItemReference
Lightweight stock-item reference (id + code + description).
| field | type | description |
|---|---|---|
id |
int |
The stock-item id. |
code |
string |
The stock-item code. |
description |
string |
The stock-item description. |
StockItemResponse
Response describing a stock item.
| field | type | description |
|---|---|---|
id |
int |
Identifier. |
code |
string |
Code. |
description |
string |
Description. |
otherLanguageDescription |
string |
Alternate-language description. |
sku |
string |
SKU. |
partNumber |
string |
Part number. |
externalId |
string |
External identifier. |
classification |
ClassificationReference |
Classification. |
brand |
BrandReference |
Brand. |
unitOfMeasureChainId |
int? |
Unit-of-measure chain identifier. |
unitOfMeasure |
int? |
Unit-of-measure identifier. |
singleUomId |
int? |
Single UOM identifier. |
primaryUomId |
int? |
Primary unit-of-measure identifier resolved from the chain. |
isGroupingItem |
bool |
Whether the item is a grouping item. |
tags |
string[] |
Item tags. |
dynamicPropertiesInfo |
List<DynamicPropertyInfo> |
Dynamic-property assignments. |
childItems |
List<StockItemChildResponse> |
Child items. |
stockItemUnitOfMeasures |
List<StockItemUnitOfMeasureResponse> |
UOM chain. |
salesPrice |
decimal |
Sales price. |
purchasePrice |
decimal |
Purchase price. |
dealerPrice |
decimal |
Dealer price. |
superDealerPrice |
decimal |
Super-dealer price. |
minimumPrice |
decimal |
Minimum price. |
referencePrice |
decimal |
Reference price. |
salesPriceDiscount |
decimal? |
The discount value applied to the sales price (interpreted per SalesPriceDiscountType). |
salesPriceDiscountType |
int? |
The discount type for the sales price (0 = amount, 1 = percentage). |
salesPriceDiscountIsLimited |
bool? |
Whether the sales-price discount is bounded by the date range below. |
salesPriceDiscountDateFrom |
DateTime? |
The start date of the sales-price discount window. |
salesPriceDiscountDateTo |
DateTime? |
The end date of the sales-price discount window. |
dealerPriceDiscount |
decimal? |
The discount value applied to the dealer price. |
dealerPriceDiscountType |
int? |
The discount type for the dealer price (0 = amount, 1 = percentage). |
dealerPriceDiscountIsLimited |
bool? |
Whether the dealer-price discount is bounded by the date range below. |
dealerPriceDiscountDateFrom |
DateTime? |
The start date of the dealer-price discount window. |
dealerPriceDiscountDateTo |
DateTime? |
The end date of the dealer-price discount window. |
superDealerPriceDiscount |
decimal? |
The discount value applied to the super-dealer price. |
superDealerPriceDiscountType |
int? |
The discount type for the super-dealer price (0 = amount, 1 = percentage). |
superDealerPriceDiscountIsLimited |
bool? |
Whether the super-dealer-price discount is bounded by the date range below. |
superDealerPriceDiscountDateFrom |
DateTime? |
The start date of the super-dealer-price discount window. |
superDealerPriceDiscountDateTo |
DateTime? |
The end date of the super-dealer-price discount window. |
averageCost |
double? |
Average cost. |
lastCost |
double? |
Last cost. |
fifo |
double? |
FIFO value. |
lifo |
double? |
LIFO value. |
openingAverageCost |
double? |
Opening average cost. |
openingFifo |
double? |
Opening FIFO valuation. |
openingLifo |
double? |
Opening LIFO valuation. |
openingLastCost |
double? |
Opening last cost. |
tax |
TaxReference |
Tax. |
taxRate |
decimal |
Tax rate. |
withholdingTax |
TaxReference |
Withholding tax. |
withholdingTaxRate |
decimal |
Withholding tax rate. |
globalOpeningBalance |
decimal |
Global opening balance. |
globalReorderingPoint |
decimal? |
Global reordering point. |
globalMinimumPoint |
decimal? |
Global minimum point. |
globalMaximumPoint |
decimal? |
Global maximum point. |
unitPrice |
decimal |
Unit price. |
length |
decimal |
Length. |
width |
decimal |
Width. |
height |
decimal |
Height. |
weight |
decimal |
Weight. |
warranty |
decimal |
Warranty. |
note |
string |
Note. |
itemLocation |
string |
Item location. |
datasheet |
string |
Datasheet. |
imageUrl |
string |
Image URL. |
parentItemId |
int? |
Parent item identifier. |
enforceSerialEntry |
bool |
Whether serial entry is enforced. |
enforceBatchNumberDateEntry |
bool |
Whether batch-number date entry is enforced. |
enforceExpirationDateEntry |
bool |
Whether expiry-date entry is enforced. |
allowSerialDuplication |
bool |
Whether serial duplication is allowed. |
autofillBatchNumber |
bool |
Whether batch numbers are autofilled. |
allowForSMS |
bool |
Whether SMS is allowed. |
StockItemUnitOfMeasureRequest
Request to create or update an entry in the stock-item unit-of-measure chain.
| field | type | validation | description |
|---|---|---|---|
unitOfMeasureId |
int |
GreaterThan(0) | The id of the unit of measure. |
uomName |
string |
MaximumLength(200) | The display name of the unit of measure as it appears for this stock item. |
uomPartNumber |
string |
MaximumLength(200) | The part number captured at this UOM level. |
uomPrice |
decimal |
The sales price at this UOM level. | |
uomDealerPrice |
decimal |
The dealer price at this UOM level. | |
uomSuperDealerPrice |
decimal |
The super-dealer price at this UOM level. | |
isPrimary |
bool |
Whether this UOM is the primary (smallest) unit of the chain. Exactly one entry must be primary. | |
ratioToPrimary |
decimal |
GreaterThan(0m) .When(x => !x.IsPrimary) | The conversion ratio to the primary UOM. 1 for the primary; larger for parent units. |
StockItemUnitOfMeasureResponse
Response describing a stock-item UOM entry.
| field | type | description |
|---|---|---|
id |
int |
Identifier. |
stockItemId |
int |
Stock-item identifier. |
unitOfMeasureId |
int |
Unit-of-measure identifier. |
uomName |
string |
UOM name. |
code |
string |
Code. |
uomPartNumber |
string |
UOM part number. |
uomPrice |
decimal |
UOM price. |
uomDealerPrice |
decimal |
Dealer price. |
uomSuperDealerPrice |
decimal |
Super-dealer price. |
ratioToPrimary |
decimal |
Ratio to the primary UOM. |
isPrimary |
bool |
Whether this is the primary UOM. |
isDefault |
bool |
Whether this is the default UOM. |
isUsedInTransaction |
bool |
Whether the UOM is used in transactions. |
uomChainName |
string |
Chain name. |
unitOfMeasureChainId |
int |
Unit-of-measure chain identifier. |
stockItemPartNumber |
string |
Stock-item part number for this UOM. |
StockItemWarehouseSummaryResponse
Response describing a stock item's sales and stock position, broken down by warehouse.
| field | type | description |
|---|---|---|
stockitemId |
int |
Stock item identifier. |
description |
string |
Description. |
partNumber |
string |
Part number. |
sku |
string |
SKU. |
warehouses |
List<StockItemWarehouseSummaryWarehouseResponse> |
Per-warehouse sales and stock position. |
StockItemWarehouseSummaryWarehouseResponse
A single warehouse's sales and stock position for a stock item.
| field | type | description |
|---|---|---|
warehouseId |
int |
Warehouse identifier. |
description |
string |
Warehouse description. |
sales |
decimal |
Sales quantity in Primary UOM for the requested period. |
salesReturn |
decimal |
Sales-return quantity in Primary UOM for the requested period. |
balance |
decimal |
Current on-hand stock balance. |
reserved |
decimal |
Reserved stock quantity. |
expectedReceive |
decimal |
Expected receiving quantity from open purchase orders. |
expectedTransfer |
decimal |
Expected incoming transfer quantity. |
TaxReference
Lightweight tax reference (id + name + rate).
| field | type | description |
|---|---|---|
id |
int |
The tax id. |
name |
string |
The tax name. |
rate |
decimal |
The tax rate as a percentage. |
WarehouseReference
Lightweight warehouse reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The warehouse id. |
code |
string |
The warehouse code. |
name |
string |
The warehouse name. |