Locations API
Overview
The Locations API provides comprehensive functionality for managing warehouse locations using a hierarchical structure. This API supports the complete location lifecycle including creation, hierarchy management, operational status control, and tree-based queries optimized for UI components.
Base URL: /api/locations
Key Features
- Hierarchical Structure: Unlimited depth parent-child relationships
- Tree Queries: Optimized endpoints for tree components
- Operational Status: Control location availability for transactions
- Physical Address Management: Optional address information for locations
- Location Classification: Type and purpose-based organization
- Advanced Filtering: Search by type, purpose, status, and term
- Soft Delete: Archive and restore with history preservation
Core Endpoints
1. Get Locations (with Filtering)
Retrieves locations with advanced filtering capabilities.
GET /api/locations?locationTypeId=1&isOperational=true&searchTerm=warehouse
Accept: application/json
Query Parameters:
locationTypeId(optional): Filter by location type ID (int)locationPurposeId(optional): Filter by location purpose ID (int)isOperational(optional): Filter by operational status (bool)searchTerm(optional): Search in code, name, or full path
Response:
[
{
"id": "loc-warehouse-001-id",
"code": "WH-MAIN",
"name": "Main Distribution Center",
"description": "Primary distribution facility - North Region",
"locationTypeId": 1,
"locationTypeName": "Warehouse",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": null,
"parentLocationCode": null,
"parentLocationName": null,
"fullPath": "Main Distribution Center",
"isOperational": true,
"physicalAddress": {
"street": "123 Industrial Parkway",
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "USA"
},
"createdDate": "2025-01-01T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
}
]
Status Codes:
200 OK- Locations retrieved successfully400 Bad Request- Invalid query parameters
2. Get Root Locations
Retrieves top-level locations (locations without parents).
GET /api/locations/root
Accept: application/json
Response:
[
{
"id": "warehouse-001-id",
"code": "WH-MAIN",
"name": "Main Distribution Center",
"description": "Primary distribution facility",
"locationTypeId": 1,
"locationTypeName": "Warehouse",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": null,
"parentLocationCode": null,
"parentLocationName": null,
"fullPath": "Main Distribution Center",
"isOperational": true,
"physicalAddress": { /* ... */ },
"createdDate": "2025-01-01T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
},
{
"id": "warehouse-002-id",
"code": "WH-SOUTH",
"name": "South Distribution Center",
"description": "Secondary facility - South Region",
"locationTypeId": 1,
"locationTypeName": "Warehouse",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": null,
"parentLocationCode": null,
"parentLocationName": null,
"fullPath": "South Distribution Center",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-10T08:00:00Z",
"modifiedDate": "2025-01-20T10:00:00Z"
}
]
Status Codes:
200 OK- Root locations retrieved successfully
3. Get Location Tree
Retrieves hierarchical tree structure optimized for tree UI components.
GET /api/locations/tree?maxDepth=3&operationalOnly=true
Accept: application/json
Query Parameters:
maxDepth(optional): Maximum depth to load (performance optimization)operationalOnly(optional): Include only operational locations (default: true)
Response:
[
{
"id": "warehouse-001-id",
"code": "WH-MAIN",
"name": "Main Distribution Center",
"locationTypeId": 1,
"locationTypeName": "Warehouse",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": null,
"isOperational": true,
"hasChildren": true,
"children": [
{
"id": "zone-a-id",
"code": "ZONE-A",
"name": "Storage Zone A",
"locationTypeId": 2,
"locationTypeName": "Zone",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "warehouse-001-id",
"isOperational": true,
"hasChildren": true,
"children": [
{
"id": "aisle-a1-id",
"code": "AISLE-A1",
"name": "Aisle A1",
"locationTypeId": 3,
"locationTypeName": "Aisle",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "zone-a-id",
"isOperational": true,
"hasChildren": false,
"children": []
}
]
}
]
}
]
Status Codes:
200 OK- Tree structure retrieved successfully
Use Cases:
- Tree view components in UI
- Location pickers with hierarchy display
- Navigation menus
- Warehouse visualization
4. Get Location by ID
Retrieves a specific location with all details.
GET /api/locations/{id}
Accept: application/json
Path Parameters:
id: Location ID (Guid)
Response:
{
"id": "zone-a-id",
"code": "ZONE-A",
"name": "Storage Zone A",
"description": "Primary storage area for general goods",
"locationTypeId": 2,
"locationTypeName": "Zone",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "warehouse-001-id",
"parentLocationCode": "WH-MAIN",
"parentLocationName": "Main Distribution Center",
"fullPath": "Main Distribution Center / Storage Zone A",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-02T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
}
Status Codes:
200 OK- Location found and returned404 Not Found- Location not found
5. Get Location by Code
Retrieves a location by its unique code.
GET /api/locations/by-code/{code}
Accept: application/json
Path Parameters:
code: Location code (string)
Response:
{
"id": "zone-a-id",
"code": "ZONE-A",
"name": "Storage Zone A",
"description": "Primary storage area for general goods",
"locationTypeId": 2,
"locationTypeName": "Zone",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "warehouse-001-id",
"parentLocationCode": "WH-MAIN",
"parentLocationName": "Main Distribution Center",
"fullPath": "Main Distribution Center / Storage Zone A",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-02T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
}
Status Codes:
200 OK- Location found404 Not Found- Location with specified code not found
6. Get Location Children
Retrieves immediate children of a location.
GET /api/locations/{id}/children
Accept: application/json
Path Parameters:
id: Parent location ID (Guid)
Response:
[
{
"id": "aisle-a1-id",
"code": "AISLE-A1",
"name": "Aisle A1",
"description": "First aisle in Zone A",
"locationTypeId": 3,
"locationTypeName": "Aisle",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "zone-a-id",
"parentLocationCode": "ZONE-A",
"parentLocationName": "Storage Zone A",
"fullPath": "Main Distribution Center / Storage Zone A / Aisle A1",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-03T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
},
{
"id": "aisle-a2-id",
"code": "AISLE-A2",
"name": "Aisle A2",
"description": "Second aisle in Zone A",
"locationTypeId": 3,
"locationTypeName": "Aisle",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "zone-a-id",
"parentLocationCode": "ZONE-A",
"parentLocationName": "Storage Zone A",
"fullPath": "Main Distribution Center / Storage Zone A / Aisle A2",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-03T08:00:00Z",
"modifiedDate": "2025-01-15T10:00:00Z"
}
]
Status Codes:
200 OK- Children retrieved successfully (empty array if no children)404 Not Found- Parent location not found
7. Create Location
Creates a new location with optional parent.
POST /api/locations
Content-Type: application/json
Request Body:
{
"code": "AISLE-A1",
"name": "Aisle A1",
"description": "First aisle in Zone A",
"locationTypeId": 3,
"locationPurposeId": 1,
"parentLocationId": "zone-a-id",
"physicalAddress": {
"street": "123 Industrial Parkway",
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "USA"
}
}
Field Descriptions:
code(required): Unique location code (auto-uppercased)name(required): Display namedescription(optional): Additional detailslocationTypeId(required): Location type (Warehouse, Zone, Aisle, etc.)locationPurposeId(required): Location purpose (Storage, Receiving, Shipping, etc.)parentLocationId(optional): Parent location ID (null for root locations)physicalAddress(optional): Physical address information
Response:
{
"id": "newly-created-location-id",
"code": "AISLE-A1",
"name": "Aisle A1",
"description": "First aisle in Zone A",
"locationTypeId": 3,
"locationTypeName": "Aisle",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "zone-a-id",
"parentLocationCode": "ZONE-A",
"parentLocationName": "Storage Zone A",
"fullPath": "Main Distribution Center / Storage Zone A / Aisle A1",
"isOperational": true,
"physicalAddress": {
"street": "123 Industrial Parkway",
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "USA"
},
"createdDate": "2025-01-24T10:00:00Z",
"modifiedDate": "2025-01-24T10:00:00Z"
}
Status Codes:
201 Created- Location created successfully400 Bad Request- Validation errors409 Conflict- Location code already exists404 Not Found- Parent location not found
8. Update Location Basic Info
Updates location name and description.
PATCH /api/locations/{id}/basic-info
Content-Type: application/json
Path Parameters:
id: Location ID (Guid)
Request Body:
{
"name": "Storage Zone A - Expanded",
"description": "Primary storage area for general goods - recently expanded"
}
Response:
{
"id": "zone-a-id",
"code": "ZONE-A",
"name": "Storage Zone A - Expanded",
"description": "Primary storage area for general goods - recently expanded",
"locationTypeId": 2,
"locationTypeName": "Zone",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "warehouse-001-id",
"parentLocationCode": "WH-MAIN",
"parentLocationName": "Main Distribution Center",
"fullPath": "Main Distribution Center / Storage Zone A - Expanded",
"isOperational": true,
"physicalAddress": null,
"createdDate": "2025-01-02T08:00:00Z",
"modifiedDate": "2025-01-24T15:30:00Z"
}
Status Codes:
200 OK- Location updated successfully400 Bad Request- Validation errors404 Not Found- Location not found
9. Update Location Purpose
Changes the location's functional purpose.
PATCH /api/locations/{id}/purpose
Content-Type: application/json
Path Parameters:
id: Location ID (Guid)
Request Body:
{
"locationPurposeId": 2
}
Response:
{
"locationPurposeId": 2,
"locationPurposeName": "Receiving"
}
Status Codes:
200 OK- Purpose updated successfully400 Bad Request- Invalid purpose ID404 Not Found- Location not found
10. Update Location Address
Updates or removes physical address.
PATCH /api/locations/{id}/address
Content-Type: application/json
Path Parameters:
id: Location ID (Guid)
Request Body (Add/Update):
{
"street": "456 New Street",
"city": "Springfield",
"state": "IL",
"postalCode": "62702",
"country": "USA"
}
Request Body (Remove):
{
"street": null,
"city": null,
"state": null,
"postalCode": null,
"country": null
}
Response (Address Set):
{
"street": "456 New Street",
"city": "Springfield",
"state": "IL",
"postalCode": "62702",
"country": "USA"
}
Response (Address Cleared):
null
Status Codes:
200 OK- Address updated successfully404 Not Found- Location not found
11. Update Operational Flags
Changes location operational status.
PATCH /api/locations/{id}/operational-flags
Content-Type: application/json
Path Parameters:
id: Location ID (Guid)
Request Body:
{
"isOperational": false
}
Response:
{
"isOperational": false
}
Status Codes:
200 OK- Status updated successfully404 Not Found- Location not found
Business Impact:
- Setting
isOperational: falseprevents location from being used in new transactions - Existing inventory at location remains (read-only)
- Location can be reactivated by setting
isOperational: true
12. Move Location
Moves a location to a new parent or to root level.
POST /api/locations/{id}/move
Content-Type: application/json
Path Parameters:
id: Location ID (Guid)
Request Body (Move to new parent):
{
"newParentLocationId": "new-parent-id"
}
Request Body (Move to root level):
{
"newParentLocationId": null
}
Response:
204 No Content
Status Codes:
204 No Content- Location moved successfully400 Bad Request- Would create circular reference404 Not Found- Location or new parent not found
13. Archive Location
Archives a location (soft delete).
DELETE /api/locations/{id}
Path Parameters:
id: Location ID (Guid)
Response:
204 No Content
Status Codes:
204 No Content- Location archived successfully404 Not Found- Location not found409 Conflict- Location has active inventory or open transactions
14. Unarchive Location
Restores an archived location.
POST /api/locations/{id}/unarchive
Path Parameters:
id: Location ID (Guid)
Response:
204 No Content
Status Codes:
204 No Content- Location restored successfully404 Not Found- Location not found400 Bad Request- Location is not archived
15. Get Archived Locations
Retrieves all archived locations.
GET /api/locations/archived
Accept: application/json
Response:
[
{
"id": "archived-location-id",
"code": "OLD-ZONE",
"name": "Old Storage Zone",
"description": "Decommissioned storage area",
"locationTypeId": 2,
"locationTypeName": "Zone",
"locationPurposeId": 1,
"locationPurposeName": "General Storage",
"parentLocationId": "warehouse-001-id",
"parentLocationCode": "WH-MAIN",
"parentLocationName": "Main Distribution Center",
"fullPath": "Main Distribution Center / Old Storage Zone",
"isOperational": false,
"physicalAddress": null,
"createdDate": "2024-01-01T00:00:00Z",
"modifiedDate": "2025-01-20T00:00:00Z"
}
]
Status Codes:
200 OK- Archived locations retrieved successfully
Response Schemas
LocationDto
interface LocationDto {
id: string; // Guid
code: string; // Unique code (uppercase)
name: string; // Display name
description: string | null; // Optional details
// Type and Purpose
locationTypeId: number; // Location type ID
locationTypeName: string; // Type display name
locationPurposeId: number; // Purpose ID
locationPurposeName: string; // Purpose display name
// Hierarchy
parentLocationId: string | null; // Guid or null for root
parentLocationCode: string | null; // Parent code
parentLocationName: string | null; // Parent name
fullPath: string; // Full hierarchical path
// Status
isOperational: boolean; // Operational status
// Address
physicalAddress: AddressDto | null; // Optional address
// Audit
createdDate: string; // ISO 8601 datetime
modifiedDate: string; // ISO 8601 datetime
}
interface AddressDto {
street: string;
city: string;
state: string;
postalCode: string;
country: string;
}
interface LocationTreeDto {
id: string;
code: string;
name: string;
locationTypeId: number;
locationTypeName: string;
locationPurposeId: number;
locationPurposeName: string;
parentLocationId: string | null;
isOperational: boolean;
hasChildren: boolean;
children: LocationTreeDto[]; // Recursive structure
}
Use Cases and Examples
Use Case 1: Create Multi-Level Warehouse Structure
# Step 1: Create warehouse (root)
POST /api/locations
{
"code": "WH-MAIN",
"name": "Main Distribution Center",
"locationTypeId": 1,
"locationPurposeId": 1,
"physicalAddress": { /* full address */ }
}
# Response: { "id": "warehouse-id", ... }
# Step 2: Create zone
POST /api/locations
{
"code": "ZONE-A",
"name": "Storage Zone A",
"locationTypeId": 2,
"locationPurposeId": 1,
"parentLocationId": "warehouse-id"
}
# Response: { "id": "zone-id", ... }
# Step 3: Create aisle
POST /api/locations
{
"code": "AISLE-A1",
"name": "Aisle A1",
"locationTypeId": 3,
"locationPurposeId": 1,
"parentLocationId": "zone-id"
}
# Result: Warehouse > Zone > Aisle hierarchy created
Use Case 2: Mark Location for Maintenance
# Set location non-operational
PATCH /api/locations/{id}/operational-flags
{
"isOperational": false
}
# Location now unavailable for new transactions
# Existing inventory remains (read-only)
# After maintenance, reactivate
PATCH /api/locations/{id}/operational-flags
{
"isOperational": true
}
Use Case 3: Reorganize Warehouse Structure
# Move aisle from Zone A to Zone B
POST /api/locations/{aisle-id}/move
{
"newParentLocationId": "zone-b-id"
}
# Aisle hierarchy path automatically updated
# Inventory locations remain consistent
Use Case 4: Load Location Picker for Transaction
# Get tree structure for UI picker
GET /api/locations/tree?operationalOnly=true&maxDepth=4
# Response: Complete tree structure
# UI renders hierarchical picker
# User selects leaf location for transaction
Error Handling
Common Error Responses
Location Code Already Exists (409 Conflict):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
"title": "Conflict",
"status": 409,
"detail": "A location with code 'WH-MAIN' already exists."
}
Circular Reference Detected (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Moving location 'ZONE-A' to 'AISLE-A1' would create a circular reference."
}
Location Not Found (404 Not Found):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"detail": "Location with ID 'a1b2c3d4-...' was not found."
}
Cannot Archive Location with Inventory (409 Conflict):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
"title": "Conflict",
"status": 409,
"detail": "Cannot archive location 'ZONE-A' because it contains active inventory."
}
Best Practices
1. Location Hierarchy Design
- Warehouse (root) → Zone → Aisle → Shelf → Bin
- Keep hierarchy depth reasonable (4-6 levels max)
- Use meaningful codes (WH-MAIN, ZONE-A, AISLE-A1)
- Set operational status at appropriate level
2. Operational Status Management
- Mark locations non-operational for maintenance
- Non-operational locations retain existing inventory
- Prevent new transactions to non-operational locations
- Use for temporary closures, renovations, or decommissioning
3. Tree Loading Optimization
- Use
maxDepthparameter for large hierarchies - Use
operationalOnly: truefor transaction pickers - Cache tree structure on client side
- Reload only when structure changes
4. Location Purpose Strategy
- General Storage: Default multi-purpose storage
- Receiving: Dock doors and receiving areas
- Shipping: Staging and shipping areas
- Quarantine: Quality hold areas
- Returns: RMA and returns processing
- Production: Manufacturing floor locations
Related APIs
- Transactions API - For transactions using locations
- Inventory API - For querying inventory by location
- Location Types API - For managing location types
- Location Purposes API - For managing purposes
Last Updated: 2025-10-24 | API Version: 1.0 | Status: Active