0

Update Inventory Level

by
Published Nov 8, 2023

Set the available or on-hand quantity of an inventory item at a location.

Script shopify Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 2 hours ago
1
//native
2

3
export type DynSelect_location_id = string
4

5
export async function location_id(auth: RT.Shopify) {
6
  const response = await fetch(
7
    `https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json`,
8
    {
9
      method: "POST",
10
      headers: {
11
        "X-Shopify-Access-Token": auth.token,
12
        "Content-Type": "application/json",
13
        Accept: "application/json",
14
      },
15
      body: JSON.stringify({
16
        query: `query { locations(first: 250) { nodes { id name } } }`,
17
      }),
18
    }
19
  )
20
  if (!response.ok) {
21
    throw new Error(`${response.status} ${await response.text()}`)
22
  }
23
  const { data, errors } = await response.json()
24
  if (errors) {
25
    throw new Error(JSON.stringify(errors))
26
  }
27
  return data.locations.nodes.map((l: { id: string; name: string }) => ({
28
    value: l.id,
29
    label: l.name,
30
  }))
31
}
32

33
/**
34
 * Update Inventory Level
35
 * Set the available (or on-hand) quantity of an inventory item at a location. The inventory item ID is on each variant (variant.inventoryItem.id). Pass change_from_quantity (the quantity you expect is there now) to fail instead of overwriting a concurrent change; leave it empty to overwrite unconditionally. The item must be tracked and stocked at the location.
36
 */
37
export async function main(
38
  auth: RT.Shopify,
39
  inventory_item_id: string,
40
  location_id: DynSelect_location_id,
41
  quantity: number,
42
  name: "available" | "on_hand" | undefined,
43
  reason:
44
    | "correction"
45
    | "cycle_count_available"
46
    | "received"
47
    | "restock"
48
    | "damaged"
49
    | "shrinkage"
50
    | "quality_control"
51
    | "promotion"
52
    | "safety_stock"
53
    | "movement_created"
54
    | "movement_updated"
55
    | "movement_received"
56
    | "movement_canceled"
57
    | "reservation_created"
58
    | "reservation_updated"
59
    | "reservation_deleted"
60
    | "other"
61
    | undefined,
62
  change_from_quantity: number | undefined,
63
  reference_document_uri: string | undefined
64
) {
65
  const inventoryItemId = inventory_item_id.startsWith("gid://")
66
    ? inventory_item_id
67
    : `gid://shopify/InventoryItem/${inventory_item_id}`
68
  const locationId = location_id.startsWith("gid://")
69
    ? location_id
70
    : `gid://shopify/Location/${location_id}`
71

72
  const response = await fetch(
73
    `https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json`,
74
    {
75
      method: "POST",
76
      headers: {
77
        "X-Shopify-Access-Token": auth.token,
78
        "Content-Type": "application/json",
79
        Accept: "application/json",
80
      },
81
      body: JSON.stringify({
82
        query: `mutation ($input: InventorySetQuantitiesInput!, $key: String!) { inventorySetQuantities(input: $input) @idempotent(key: $key) { inventoryAdjustmentGroup { id createdAt reason referenceDocumentUri changes { name delta quantityAfterChange item { id } location { id name } } } userErrors { field message code } } }`,
83
        variables: {
84
          key: crypto.randomUUID(),
85
          input: {
86
            name: name || "available",
87
            reason: reason || "correction",
88
            referenceDocumentUri: reference_document_uri || undefined,
89
            quantities: [
90
              {
91
                inventoryItemId,
92
                locationId,
93
                quantity,
94
                // mandatory since 2026-04: null skips the compare-and-swap check
95
                changeFromQuantity: change_from_quantity ?? null,
96
              },
97
            ],
98
          },
99
        },
100
      }),
101
    }
102
  )
103

104
  if (!response.ok) {
105
    throw new Error(`${response.status} ${await response.text()}`)
106
  }
107

108
  const { data, errors } = await response.json()
109
  if (errors) {
110
    throw new Error(JSON.stringify(errors))
111
  }
112
  if (data.inventorySetQuantities.userErrors.length) {
113
    throw new Error(JSON.stringify(data.inventorySetQuantities.userErrors))
114
  }
115

116
  return data.inventorySetQuantities
117
}
118

Other submissions
  • Submitted by hugo697 Typescript (fetch-only)
    Created 528 days ago
    1
    type Shopify = {
    2
      token: string;
    3
      store_name: string;
    4
    };
    5
    /**
    6
     * Sets the inventory level for an inventory item at a location
    7
     * Sets the inventory level for an inventory item at a location. If the specified location is not connected, it will be automatically connected first. When connecting inventory items to locations, it's important to understand the rules around fulfillment service locations.
    8
     */
    9
    export async function main(
    10
      auth: Shopify,
    11
      api_version: string = "2023-10",
    12
      body: {
    13
        available?: number;
    14
        inventory_item_id?: number;
    15
        location_id?: number;
    16
        [k: string]: unknown;
    17
      }
    18
    ) {
    19
      const url = new URL(
    20
        `https://${auth.store_name}.myshopify.com/admin/api/${api_version}/inventory_levels/set.json`
    21
      );
    22
    
    
    23
      const response = await fetch(url, {
    24
        method: "POST",
    25
        headers: {
    26
          "Content-Type": "application/json",
    27
          "X-Shopify-Access-Token": auth.token,
    28
        },
    29
        body: JSON.stringify(body),
    30
      });
    31
      if (!response.ok) {
    32
        const text = await response.text();
    33
        throw new Error(`${response.status} ${text}`);
    34
      }
    35
      return await response.json();
    36
    }
    37