> For the complete documentation index, see [llms.txt](https://docs.fulfillmenttools.com/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fulfillmenttools.com/documentation/by-pillar/global-inventory-hub/storage-locations-and-zones.md).

# Storage locations and zones

[Storage locations](#storage-location) and [zones](#zones) help locate items easily during the fulfillment process. You can use them independently or together.

## Storage location

A storage location is a physical place where you can store [stock](/documentation/by-pillar/global-inventory-hub/stock.md). Since more than one product may be stored in the same location, multiple stock items can be connected to a single storage location.

Depending on the facility type, a storage location can represent different concepts, for example, the showcase area, the supply room in stores, a compartment on the shelf, or a pallet space in warehouses.

Storage locations represent the available storage space in a facility. You can assign stock to a facility, or to a specific storage location by linking the stock to the location.

* Storage locations can be grouped in [zones](#zones).
* Storage locations can be assigned [traits](/documentation/by-pillar/global-inventory-hub/inventory-traits.md), which they in turn inherit to all stocks linked to them.

### Running sequences on storage locations

​You can order storage locations in a (running) sequence by defining the previous and next location.

Depending on the sequence type that was defined, the sequence is considered in picking or stowing.

{% hint style="warning" %}
The running sequence defined for a storage location takes priority over the running sequence set at the listing or order line item level.
{% endhint %}

### Storage location types

Storage locations can have the type `SINGLE_STORAGE` or `BULK_STORAGE`.

#### Single storage

On locations with type `SINGLE_STORAGE`, you can store multiple items of the same product (for example, 100 apples). If a product is already placed on a single-storage location, you can't stow a different product in the same location.

#### Bulk storage

On locations with type `BULK_STORAGE`, you can store different products, for example, 100 apples and 100 bananas.

### Storage location recommendations

#### Working principle

A recommendation is requested for an existing [stock](/documentation/by-pillar/global-inventory-hub/stock.md) based on its stock ID. The product (`tenantArticleId`), [stock properties](/documentation/by-pillar/global-inventory-hub/stock/stock-properties.md) (for example, expiry, batch), and current [storage location](/documentation/backoffice/facility-view/inventory/storage-locations.md) are considered.

Only storage locations in the current facility that are [accessible](/documentation/by-pillar/global-inventory-hub/inventory-traits.md) and not the current storage location are considered for further evaluation.

1. The priority is a storage location with the same product and the same [properties](/documentation/by-pillar/global-inventory-hub/stock/stock-properties.md). This ensures that stocks which are treated the same by other processes are kept together.
2. Alternatively, if [mixed storage](/documentation/by-pillar/global-inventory-hub/configurations.md#unmixed-storage-configuration) is enabled, fulfillmenttools considers storage locations with the same product but different properties.

In both cases, if multiple storage locations are found, the locations with the least combined stock are preferred. The idea is to spread stock evenly across storage locations and avoid overloading some locations.

If no storage locations are found via the rules described in (1) or (2), nothing is recommended.

{% hint style="success" %}
**"Keep on zero" for storage location recommendations**

When using storage location recommendations, it can help to set the [keep on zero](/documentation/by-pillar/global-inventory-hub/inventory-traits.md) trait on storage locations. When the trait is set, fulfillmenttools doesn't delete stocks with value 0 from the location. As a result, fulfillmenttools still knows an item is supposed to be stowed in the location even after stock levels drop to 0.
{% endhint %}

The diagram below covers common problems when investigating why an expected location isn't recommended when stowing.

<figure><img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2F7fJqqkGsg3D0zUkGiprf%2FStorage%20location%20recommendations%20decision%20flow.png?alt=media&amp;token=e8cda26f-37ea-4fb9-8f0d-ca5f1afe45ae" alt=""><figcaption></figcaption></figure>

### Create a storage location

Storage locations are always related to a specific facility. So, to create a storage location, you need to first [create a facility](/documentation/getting-started/facilities.md).

The example below creates a disabled storage location with the `ACCESSIBLE` trait. This means that stock in this location will not be considered for incoming orders and can't be picked.

```http
POST https://{YOUR_TENANT_NAME}.api.fulfillmenttools.com/api/facilities/{YOUR_FACILITY_ID}/storagelocations
```

{% tabs %}
{% tab title="Request body" %}

```json
{
    "tenantLocationId": "qa-location-01",
    "name": "QA on Hold 01",
    "type": "SINGLE_STORAGE",
    "runningSequences": [],
    "scannableCodes": [],
    "traitConfig": [
        {
            "trait": "ACCESSIBLE",
            "enabled": false
        }
    ]
}
```

{% endtab %}

{% tab title="Response body" %}

```json
{
    "name": "QA on Hold 01",
    "tenantLocationId": "qa-location-01",
    "type": "SINGLE_STORAGE",
    "traits": [
        "PICKABLE",
        "ACCESSIBLE"
    ],
    "traitConfig": [
        {
            "trait": "ACCESSIBLE",
            "enabled": true
        }
    ],
    "scannableCodes": [],
    "runningSequences": [],
    "facilityRef": "{YOUR_FACILITY_ID}",
    "version": 1,
    "lastModified": "2026-03-05T16:46:46.052Z",
    "id": "{YOUR_STORAGE_LOCATION_ID}",
    "created": "2026-03-05T16:46:46.052Z"
}
```

{% endtab %}
{% endtabs %}

## Zones

A zone represents a physical area in the facility. Zones and storage locations can exist separately. When you use both, we recommend assigning [storage locations](#storage-location) to the zone they are in.

You can create a zone using the `/api/facilities/{facilityId}/zones` endpoint. Then, assign storage locations to that zone using the `zoneRef` field on the [storage location endpoint](#create-a-storage-location).

Products get linked to a zone only because their stock sits in one of those storage locations. A listing itself has no zone field.

A user can be assigned to one or more zones, set via `assignedZones` on their [assigned facility](/documentation/apis/api-reference/user-management-core.md#post-api-users-userid-assignedfacilities). You can then filter pick jobs by zone using the `zoneRefs` query-string parameter. A pick job can contain items from several zones at once, as only one pick job will be created. The pick job lists all the zones it touches in `pickingZones`. Each line item also carries its own zone, via `zoneRef` inside its `partialStockLocations`. See also the [Zone picking section of the Picking article](/documentation/by-pillar/store-operations/picking.md).

{% hint style="info" %}
Filtering pick jobs by zone decides which jobs show up in a list. It doesn't split a job into smaller pieces, and it doesn't hide items from a user once they open the job.
{% endhint %}

Below is an example of what a pick job with zones looks like:

```json
{
  "id": "01a08610-7794-707d-ac47-e1c6e31b0b35",
  "status": "OPEN",
  "pickingZones": [
    { "zoneRef": "zoneA" },
    { "zoneRef": "zoneB" },
    { "zoneRef": "zoneC" }
  ],
  "pickLineItems": [
    {
      "id": "line-A",
      "article": { "tenantArticleId": "A" },
      "quantity": 1,
      "picked": 0,
      "partialStockLocations": [
        { "stockRef": "stock-A", "quantity": 1, "zoneRef": "zoneA" }
      ]
    },
    {
      "id": "line-B",
      "article": { "tenantArticleId": "B" },
      "quantity": 1,
      "picked": 0,
      "partialStockLocations": [
        { "stockRef": "stock-B", "quantity": 1, "zoneRef": "zoneB" }
      ]
    },
    {
      "id": "line-C",
      "article": { "tenantArticleId": "C" },
      "quantity": 1,
      "picked": 0,
      "partialStockLocations": [
        { "stockRef": "stock-C", "quantity": 1, "zoneRef": "zoneC" }
      ]
    }
  ]
}
```

### Create a zone

To create a zone, use the endpoint below. As a zone is part of a facility, you must create a facility first.

```http
POST https://{YOUR_TENANT_NAME}.api.fulfillmenttools.com/api/facilities/{YOUR_FACILITY_ID}/zones
```

{% tabs %}
{% tab title="Request body" %}

```json
{
  "name": "Holding",
  "score": 0
}
```

{% endtab %}

{% tab title="Response body" %}

```json
{
    "name": "Holding",
    "score": 0,
    "facilityRef": "{YOUR_FACILITY_ID}",
    "lastModified": "2026-03-05T16:50:55.153Z",
    "version": 1,
    "id": "{YOUR_ZONE_ID}",
    "created": "2026-03-05T16:50:55.153Z"
}
```

{% endtab %}
{% endtabs %}

### Add a storage location to a zone

To add a storage location to a zone, you can either create the storage location with the zone already included, or update an existing storage location to include a new zone.

```http
POST https://{YOUR_TENANT_NAME}.api.fulfillmenttools.com/api/facilities/{YOUR_FACILITY_ID}/storagelocations
```

```http
PUT https://{YOUR_TENANT_NAME}.api.fulfillmenttools.com/api/facilities/{YOUR_FACILITY_ID}/storagelocations/{YOUR_STORAGE_LOCATION_ID}
```

{% tabs %}
{% tab title="Request body" %}

```json
{
    "tenantLocationId": "qa-location-01",
    "name": "QA on Hold 01",
    "type": "SINGLE_STORAGE",
    "runningSequences": [],
    "scannableCodes": [],
    "zoneRef": "{YOUR_ZONE_ID}",
    "traitConfig": [
        {
            "trait": "ACCESSIBLE",
            "enabled": true
        }
    ]
}
```

{% endtab %}

{% tab title="Response body" %}

```json
{
    "name": "QA on Hold 01",
    "tenantLocationId": "qa-location-01",
    "type": "SINGLE_STORAGE",
    "traits": [
        "PICKABLE",
        "ACCESSIBLE"
    ],
    "traitConfig": [
        {
            "trait": "ACCESSIBLE",
            "enabled": true
        }
    ],
    "scannableCodes": [],
    "runningSequences": [],
    "zoneRef": "{YOUR_ZONE_ID}",
    "facilityRef": "{YOUR_FACILITY_ID}",
    "version": 1,
    "lastModified": "2026-09-14T10:19:00.357Z",
    "id": "01a09f6d-5f70-7648-805f-e3e8e75ce360",
    "created": "2026-09-14T10:19:00.357Z"
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.fulfillmenttools.com/documentation/by-pillar/global-inventory-hub/storage-locations-and-zones.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
