انتقل إلى المحتوى الرئيسي

Items API

Overview

The Items API provides comprehensive functionality for managing item master data using a composition-based architecture. This API supports the complete item lifecycle from creation through updates, archival, and restoration, with full support for stockable behavior management.

Base URL: /api/items

Key Features

  • Composition-Based Architecture: Flexible item model with optional stockable behavior
  • Advanced Filtering: Search by term, category, unit class, and stockable status
  • Pagination Support: Efficient handling of large item catalogs
  • Soft Delete: Archive and restore capabilities with complete history
  • Unit Class Flexibility: Items reference unit classes, not specific units
  • Category Classification: Optional hierarchical categorization

Core Endpoints

1. Get All Items (with Filtering)

Retrieves items with advanced filtering and pagination support.

GET /api/items?searchTerm=widget&categoryId={guid}&isStockable=true&pageNumber=1&pageSize=50
Accept: application/json

Query Parameters:

  • searchTerm (optional): Search across item number, name, and description
  • categoryId (optional): Filter by category ID (Guid)
  • unitClassId (optional): Filter by unit class ID (Guid)
  • isStockable (optional): Filter by stockable status
    • null - All items
    • true - Stockable items only
    • false - Non-stockable items only
  • pageNumber (optional): Page number, 1-based (default: 1)
  • pageSize (optional): Items per page (default: 50, max: 200)

Response:

[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"itemNumber": "WIDGET-001",
"name": "Premium Widget",
"description": "High-quality widget for manufacturing",
"categoryId": "cat-12345",
"categoryName": "Widgets",
"categoryPath": "Products > Widgets",
"defaultUnitClassId": "unit-class-weight",
"defaultUnitClassName": "Weight",
"taxGroupId": "tax-group-standard",
"taxGroupName": "Standard Tax",
"isStockable": true,
"stockableBehavior": {
"allowNegativeStock": false,
"trackByLocation": true
},
"isActive": true,
"createdDate": "2025-01-15T10:00:00Z",
"modifiedDate": "2025-01-20T14:30:00Z"
}
]

Status Codes:

  • 200 OK - Items retrieved successfully
  • 400 Bad Request - Invalid query parameters

2. Get Item by ID

Retrieves a specific item with all details including stockable behavior.

GET /api/items/{id}
Accept: application/json

Path Parameters:

  • id: Item ID (Guid)

Response:

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"itemNumber": "RM-STEEL-001",
"name": "Steel Plate 1/4 inch",
"description": "Cold rolled steel plate, 1/4 inch thickness",
"categoryId": "raw-materials-category-id",
"categoryName": "Raw Materials",
"categoryPath": "Materials > Metals > Steel",
"defaultUnitClassId": "weight-unit-class-id",
"defaultUnitClassName": "Weight",
"taxGroupId": "raw-materials-tax-group",
"taxGroupName": "Raw Materials Tax",
"isStockable": true,
"stockableBehavior": {
"allowNegativeStock": false,
"trackByLocation": true
},
"isActive": true,
"createdDate": "2025-01-10T08:00:00Z",
"modifiedDate": "2025-01-15T12:00:00Z"
}

Status Codes:

  • 200 OK - Item found and returned
  • 404 Not Found - Item with specified ID not found

3. Create Item

Creates a new item with optional stockable behavior.

POST /api/items
Content-Type: application/json

Request Body:

{
"itemNumber": "WIDGET-100",
"name": "Standard Widget",
"description": "General purpose widget for assembly operations",
"categoryId": "widget-category-id",
"defaultUnitClassId": "weight-unit-class-id",
"taxGroupId": "standard-tax-group-id",
"allowNegativeStock": false,
"trackByLocation": true
}

Field Descriptions:

  • itemNumber (required): Unique item identifier
  • name (required): Display name for the item
  • description (optional): Detailed description
  • categoryId (optional): Category assignment
  • defaultUnitClassId (optional): Default unit class for transactions
  • taxGroupId (optional): Tax group for finance integration
  • allowNegativeStock (optional): Enable stockable behavior with negative stock control
  • trackByLocation (optional): Enable stockable behavior with location tracking

Stockable Behavior Logic:

  • If allowNegativeStock or trackByLocation is provided → Item created with StockableBehavior
  • If both are null/omitted → Item created without StockableBehavior (non-stockable)

Response:

{
"id": "newly-created-item-id",
"itemNumber": "WIDGET-100",
"name": "Standard Widget",
"description": "General purpose widget for assembly operations",
"categoryId": "widget-category-id",
"categoryName": "Widgets",
"categoryPath": "Products > Widgets",
"defaultUnitClassId": "weight-unit-class-id",
"defaultUnitClassName": "Weight",
"taxGroupId": "standard-tax-group-id",
"taxGroupName": "Standard Tax",
"isStockable": true,
"stockableBehavior": {
"allowNegativeStock": false,
"trackByLocation": true
},
"isActive": true,
"createdDate": "2025-01-24T10:00:00Z",
"modifiedDate": "2025-01-24T10:00:00Z"
}

Status Codes:

  • 201 Created - Item created successfully
  • 400 Bad Request - Validation errors
  • 409 Conflict - Item number already exists

4. Update Item

Updates basic item information and stockable behavior.

PATCH /api/items/{id}
Content-Type: application/json

Path Parameters:

  • id: Item ID (Guid)

Request Body:

{
"name": "Premium Widget - Updated",
"description": "Enhanced widget with improved specifications",
"categoryId": "new-category-id",
"defaultUnitClassId": "new-unit-class-id",
"taxGroupId": "new-tax-group-id",
"allowNegativeStock": true,
"trackByLocation": false
}

Field Descriptions:

  • name (required): Updated display name
  • description (optional): Updated description
  • categoryId (optional): New category or null to clear
  • defaultUnitClassId (optional): New unit class or null to clear
  • taxGroupId (optional): New tax group or null to clear
  • allowNegativeStock (optional): Update or add stockable behavior
  • trackByLocation (optional): Update or add stockable behavior

Stockable Behavior Update Logic:

  • Both allowNegativeStock and trackByLocation null → Remove stockable behavior (make non-stockable)
  • One or both provided → Create or update stockable behavior

Response:

{
"id": "item-id",
"itemNumber": "WIDGET-100",
"name": "Premium Widget - Updated",
"description": "Enhanced widget with improved specifications",
"categoryId": "new-category-id",
"categoryName": "New Category",
"categoryPath": "Products > New Category",
"defaultUnitClassId": "new-unit-class-id",
"defaultUnitClassName": "New Unit Class",
"taxGroupId": "new-tax-group-id",
"taxGroupName": "New Tax Group",
"isStockable": true,
"stockableBehavior": {
"allowNegativeStock": true,
"trackByLocation": false
},
"isActive": true,
"createdDate": "2025-01-24T10:00:00Z",
"modifiedDate": "2025-01-24T15:30:00Z"
}

Status Codes:

  • 200 OK - Item updated successfully
  • 400 Bad Request - Validation errors
  • 404 Not Found - Item not found

5. Archive Item

Archives an item (soft delete).

DELETE /api/items/{id}

Path Parameters:

  • id: Item ID (Guid)

Response:

204 No Content

Status Codes:

  • 204 No Content - Item archived successfully
  • 404 Not Found - Item not found
  • 409 Conflict - Item cannot be archived (has active references)

Notes:

  • Item is not deleted from database, just marked inactive (IsActive = false)
  • Archived items cannot be used in new transactions
  • Existing references remain intact
  • Can be restored using unarchive endpoint

6. Unarchive Item

Restores an archived item.

POST /api/items/{id}/unarchive

Path Parameters:

  • id: Item ID (Guid)

Response:

204 No Content

Status Codes:

  • 204 No Content - Item restored successfully
  • 404 Not Found - Item not found
  • 400 Bad Request - Item is not archived

7. Get Archived Items

Retrieves all archived items.

GET /api/items/archived
Accept: application/json

Response:

[
{
"id": "archived-item-id",
"itemNumber": "OBSOLETE-001",
"name": "Obsolete Widget",
"description": "No longer in use",
"categoryId": null,
"categoryName": null,
"categoryPath": null,
"defaultUnitClassId": null,
"defaultUnitClassName": null,
"taxGroupId": null,
"taxGroupName": null,
"isStockable": false,
"stockableBehavior": null,
"isActive": false,
"createdDate": "2024-01-01T00:00:00Z",
"modifiedDate": "2025-01-20T00:00:00Z"
}
]

Status Codes:

  • 200 OK - Archived items retrieved successfully

Response Schema

ItemDto

interface ItemDto {
id: string; // Guid
itemNumber: string; // Unique business identifier
name: string; // Display name
description: string | null; // Optional details

// Category
categoryId: string | null; // Guid or null
categoryName: string | null; // Display name
categoryPath: string | null; // Full hierarchy path

// Unit Class
defaultUnitClassId: string | null; // Guid or null
defaultUnitClassName: string | null; // Display name

// Tax Group
taxGroupId: string | null; // Guid or null
taxGroupName: string | null; // Display name

// Stockable Behavior
isStockable: boolean; // Computed from behavior presence
stockableBehavior: StockableBehaviorDto | null;

// Audit Fields
isActive: boolean; // Soft delete flag
createdDate: string; // ISO 8601 datetime
modifiedDate: string; // ISO 8601 datetime
}

interface StockableBehaviorDto {
allowNegativeStock: boolean; // Allow inventory to go negative
trackByLocation: boolean; // Require location for transactions
}

Use Cases and Examples

Use Case 1: Create Stockable Item for Raw Materials

# Create steel plate item with inventory tracking
POST /api/items
{
"itemNumber": "RM-STEEL-001",
"name": "Steel Plate 1/4 inch",
"description": "Cold rolled steel plate, 1/4 inch thickness",
"categoryId": "raw-materials-category-id",
"defaultUnitClassId": "weight-unit-class-id",
"taxGroupId": "raw-materials-tax-group",
"allowNegativeStock": false,
"trackByLocation": true
}

# Response: Item created with stockable behavior
# Can now be used in inventory transactions
# Requires location specification on all transactions
# Will prevent negative stock

Use Case 2: Create Non-Stockable Service Item

# Create service item without inventory tracking
POST /api/items
{
"itemNumber": "SRV-INSTALL",
"name": "Installation Service",
"description": "Professional installation service - hourly rate",
"categoryId": "services-category-id"
# Note: No allowNegativeStock or trackByLocation = non-stockable
}

# Response: Item created without stockable behavior
# Can be used for billing and documentation
# Will NOT track inventory
# Cannot be used in inventory transactions

Use Case 3: Convert Non-Stockable to Stockable

# Update existing non-stockable item to stockable
PATCH /api/items/{id}
{
"name": "Widget XYZ",
"allowNegativeStock": true,
"trackByLocation": true
}

# Response: Item now has stockable behavior
# Inventory tracking enabled
# Can now be used in transactions

Use Case 4: Search Stockable Items by Category

# Find all stockable items in specific category
GET /api/items?categoryId=widget-category-id&isStockable=true&pageSize=100

# Returns: All stockable items in widget category
# Useful for inventory reports
# Can be filtered further with searchTerm

Use Case 5: Find Items Needing Unit Class Assignment

# Find items without unit class
GET /api/items?unitClassId=null

# Returns: Items that need unit class configuration
# Useful for data cleanup
# Items without unit class have limited transaction support

Error Handling

Common Error Responses

Item Number Already Exists (409 Conflict):

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
"title": "Conflict",
"status": 409,
"detail": "An item with number 'WIDGET-001' already exists."
}

Validation Error (400 Bad Request):

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Validation Error",
"status": 400,
"errors": {
"itemNumber": ["Item number is required."],
"name": ["Item name is required."]
}
}

Item Not Found (404 Not Found):

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"detail": "Item with ID 'a1b2c3d4-e5f6-7890-abcd-ef1234567890' was not found."
}

Cannot Archive Item with Active References (409 Conflict):

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
"title": "Conflict",
"status": 409,
"detail": "Cannot archive item 'WIDGET-001' because it has active references in BOMs or open transactions."
}

Best Practices

1. Item Creation Strategy

// For physical products (stockable)
const stockableItem = {
itemNumber: "PROD-001",
name: "Physical Product",
allowNegativeStock: false, // Strict inventory control
trackByLocation: true // Required for warehouse management
};

// For services (non-stockable)
const serviceItem = {
itemNumber: "SRV-001",
name: "Service Item"
// No stockable properties = non-stockable
};

2. Search and Filter Optimization

  • Use searchTerm for general searches (searches number, name, description)
  • Use isStockable to separate physical products from services
  • Use categoryId for category-specific reports
  • Use pagination for large catalogs (pageSize: 50-100)

3. Unit Class Assignment

  • Assign unit class at creation if known
  • Use Weight class for materials measured by weight
  • Use Count class for discrete items (each, dozen)
  • Use Volume class for liquids and gases
  • Items without unit class have limited transaction support

4. Stockable Behavior Management

  • Set allowNegativeStock: false for strict inventory control
  • Set allowNegativeStock: true for backorder support
  • Set trackByLocation: true for warehouse management
  • Set trackByLocation: false for simplified tracking


Last Updated: 2025-10-24 | API Version: 1.0 | Status: Active