Inventory

Inventory

If you are using Dynamic Slotting, this section will explain the basic mutations and queries available:

Also, for managing Inventory through our API we have two powerful tools:

Managing Inventory on Dynamic Slotting Accounts

If you are using Dynamic Slotting, you might need to use the following queries & mutations when managing Inventory:

Location Query

This query will allow you to get the location’s name, warehouse_id or type by using the location’s id.

query {
  location(id: "QmluOjIyNDMwNDY=") {
    request_id
    complexity
    data {
      legacy_id
      name
      warehouse_id
      type {
        name
      }
    }
  }
}

You should get something like this:

{
  "data": {
    "location": {
      "request_id": "5f5692457acb6db59e0d556e",
      "complexity": 1,
      "data": {
        "legacy_id": 2243046,
        "name": "01PE06CC02",
        "warehouse_id": "V2FyZWhvdXNlOjExNzkw",
        "type": {
          "name": "Bin"
        }
      }
    }
  }
}

Locations Query

This query will allow you to navigate through all the locations on a specific warehouse, for example, for warehouse_id = “V2FyZWhvdXNlOjExNzkw” if you try the following query:

query {
  locations(warehouse_id: "V2FyZWhvdXNlOjExNzkw") {
    request_id
    data {
      edges {
        node {
          id
          name
          zone
          type {
            name
          }
          pickable
          sellable
        }
      }
    }
  }
}

You should get something like this:

{
  "data": {
    "locations": {
      "request_id": "5ecbfee8e0e42dd4a4e13928",
      "data": {
        "edges": [
           {
            "node": {
              "id": "QmluOjE0OTQxMDg=",
              "name": "Bin BO",
              "zone": "A",
              "type": "Pallet storage",
              "pickable": false,
              "sellable": false
            }
          },
          {
            "node": {
              "id": "QmluOjEGehEDg=",
              "name": "Bin-A1",
              "zone": "A",
              "type": "Pallet storage",
              "pickable": true,
              "sellable": true
            }
          }]
      }
    }
  }
}

Locations list for a specific Product Query

If you need to get all the existing locations for a specific SKU, you can use the location’s connection on the Product Query, for example, for SKU:“1122334458”

query {
  product(sku: "1122334458") {
    request_id
    data {
      sku
      name
      warehouse_products {
        warehouse_id
        locations {
          edges {
            node {
              location_id
              quantity
            }
          }
        }
      }
    }
  }
}

And the response should be all of its locations on the different warehouses:

{
  "data": {
    "product": {
      "request_id": "5ecc00a2075127485340d212",
      "data": {
        "sku": "1122334458",
        "name": "Test Product 4",
        "warehouse_products": [
          {
            "warehouse_id": "V2FyZWhvdXNlOjExNzkw",
            "locations": {
              "edges": [
                {
                  "node": {
                    "location_id": "QmluOjE0OTQxMDg=",
                    "quantity": 0
                  }
                },
                {
                  "node": {
                    "location_id": "QmluOjE0OTQxMTM=",
                    "quantity": 18387
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Create a new Location Mutation

If you need to create a new Location, you can use the location_create mutation, for example:

mutation {
  location_create(data: {
    warehouse_id: "V2FyZWhvdXNlOjExNzkw",
    name: "Bin-12345"
    zone: "C2"
    pickable: false
    sellable: false
  }) {
    request_id
    location {
      name
      zone
      type {
        name
      }
      pickable
      sellable
    }
  }
}

Update an existing Location Mutation

You can also edit the settings on an existing location by using the location_update mutation and using the location_id, for example:

mutation {
  location_update(data: {
    location_id: "123BVerb3456jnx"
    pickable: true
    sellable: true
  }) {
    request_id
    location {
      name
      zone
      type {
        name
      }
      pickable
      sellable
    }
  }
}

Inventory add / Inventory remove Mutations

When removing or adding inventory for a specific SKU on a location, you can use both inventory_add and inventory_remove mutations. They both work similar, for example:

mutation {
  inventory_add(data: {
    sku: "1122334458",
    warehouse_id: "V2FyZWhvdXNlOjExNzkw",
    location_id: "QmluOjE0OTQxMDg="
    quantity: 1
    reason: "Test removing inventory from Public API"
  }) {
    request_id
    warehouse_product {
      locations {
        edges {
          node {
            location_id
            quantity
          }
        }
      }
    }
  }
}

If you are going to perform this on a 3PL account you should also include the customer_account_id

Inventory Replace Mutation

This mutation works similar to what add or remove does, but it replaces the existing inventory on that location, for example:

mutation {
  inventory_replace(data: {
    sku: "1122334458",
    warehouse_id: "V2FyZWhvdXNlOjExNzkw",
    location_id: "QmluOjE0OTQxMDg="
    quantity: 5
    reason: "Testing replacing inventory from Public API"
    includes_non_sellable: False
  }) {
    request_id
    warehouse_product {
      locations {
        edges {
          node {
            location_id
            quantity
          }
        }
      }
    }
  }

This action will replace all the inventory for that Location on the Warehouse.
If the action is performed on a 3PL account, customer_account_id should also be included.

Inventory Sync

In this section, we will explore some examples of how can you use Inventory Sync.

Note

For better readability, all of the available fields may not be included in our example queries. To navigate through the Schema and see all of the fields available, please check our Documentation section.

Overview

In this section, we will explore some examples of how you can use the Inventory Sync feature to Sync inventory using a CSV file.

This new Feature resembles the one availabe on our Web App through Inventory Upload.

For these examples, we will follow this flow:

  1. Upload a CSV file using inventory_sync mutation
  2. Check all the inventory_sync_statuses by using a query
  3. Check a particular inventory_sync_status using a query
  4. Check all the rows of that batch with an inventory_sync_items_status query

Inventory sync Mutation

In this example you will use the inventory_sync Mutation, that allows you to upload inventory:

mutation{
  inventory_sync(data:{
    url:"https://some-url.com/inv-sync.csv",
    warehouse_id:"V2FyZdfhens73hsA="
  }){
    request_id
    complexity
    sync_id
  }
}

And the response for it should be something like this:

{
  "data": {
    "inventory_sync": {
      "request_id": "5d9624af8f00587f435deb37",
      "complexity": 0,
      "sync_id": "5d9624b054de070001fd315a"
    }
  }
}

Important

  • Fields that need to be on the CSV file are: #sku, quantity, action, reason and in case the account has Dynamic Slotting, location.
  • For Dymanic Slotting account, if you don’t include location it will be assigned to an unassigned bin.
  • All SKUs included must be existing SKUs and available on that specific warehouse.
  • CSV file also needs to be available for download without any type of credentials needed.
  • Only replace is supported for action.
  • CSV file shouldn’t have over 3000 lines to achieve optimal processing performance.
  • For an example CSV file, please see:

Inventory sync statuses Query

This query allows you to get the status from all the sync batches you have

query {
  inventory_sync_statuses {
    request_id
    complexity
    data(first:3) {
      edges {
        node {
          id
          url
          user_id
          account_id
          warehouse_id
          customer_account_id
          total_count
          status
          error
          created_at
          updated_at
        }
      }
    }
  }
}

And the response should look something like this:

{
  "data": {
    "inventory_sync_statuses": {
      "request_id": "5d9654d6d49dd410acb3f5644",
      "complexity": 11,
      "data": {
        "edges": [
          {
            "node": {
              "id": "5d9624b054de070001fd315",
              "url": "https://some-url.com/inv-sync.csv",
              "user_id": "VXNlcjo5MTIp",
              "account_id": "iWNjb3VudDozODA1",
              "warehouse_id": "V2FyZWh3eXNlOjQzNTA=",
              "total_count": 3,
              "status": "error",
              "error": "error in 3 out of 3 rows",
              "created_at": "2019-10-03T16:41:20+00:00",
              "updated_at": "2019-10-03T16:41:21+00:00"
            }
          },
          {
            "node": {
              "id": "5d95fc1754de070001fd30a",
              "url": "https://some-url2.com/inv-sync.csv",
              "user_id": "VXNlcjo5MTIp",
              "account_id": "iWNjb3VudDozODA1",
              "warehouse_id": "V2FyZWh3eXNlOjQzNTA=",
              "total_count": 178,
              "status": "error",
              "error": "error in 178 out of 178 rows",
              "created_at": "2019-10-03T13:48:07+00:00",
              "updated_at": "2019-10-03T13:48:14+00:00"
            }
          },
          {
            "node": {
              "id": "5d95f884f5189700012e690",
              "url": "https://some-url.com/inv-sync.csv",
              "user_id": "VXNlcjo5MTIp",
              "account_id": "QWNjb3VudDozODA1",
              "warehouse_id": "V2FyZWhvdXNlOjQzNTA=",
              "total_count": 3,
              "status": "error",
              "error": "error in 3 out of 3 rows",
              "created_at": "2019-10-03T13:32:52+00:00",
              "updated_at": "2019-10-03T13:32:59+00:00"
            }
          }
        ]
      }
    }
  }
}

Inventory sync status Query

This query allows you to get the status of a specific sync batch

query{
  inventory_sync_status(id:"5d9624b054de070001fd3132"){
    request_id
    complexity
    data{
       id
    url
    user_id
    account_id
    warehouse_id
    customer_account_id
    total_count
    status
    error
    created_at
    updated_at
    }
  }
}

And the response should look something like this:

{
  "data": {
    "inventory_sync_status": {
      "request_id": "5d9624b054de070001fd3132",
      "complexity": 1,
      "data": {
        "id": "5d9b6a3ba1361e00012268ea",
        "url": "https://some-url.com/inv-sync.csv",
        "user_id": "VXNlcjo5MTIz",
        "account_id": "QWNjb3VudDozODAx",
        "warehouse_id": "V2FyZWhvdXNlOjY1NDU=",
        "customer_account_id": null,
        "total_count": 5,
        "status": "success",
        "error": null,
        "created_at": "2019-10-07T16:39:23+00:00",
        "updated_at": "2019-10-07T16:39:24+00:00"
      }
    }
  }
}

Inventory sync items status Query

This query allows you to get status for every row inserted from a specific sync batch

query {
  inventory_sync_items_status(id: "5d9625ebd49dd410acb3f554") {
    request_id
    data {
      edges {
        node {
          id
          row
          sku
          quantity
          action
          reason
          location
          status
          error
          created_at
          updated_at
        }
      }
    }
  }
}

And the response should look something like this:

{
  "data": {
    "inventory_sync_items_status": {
      "request_id": "5d9b6adb2e9fef31169533f8",
      "complexity": 101,
      "data": {
        "edges": [
          {
            "node": {
              "id": "5d9b6a3ba1361e00012268e8",
              "row": 1,
              "sku": "45933041",
              "quantity": 10,
              "action": "change",
              "reason": "Reason for changing inventory",
              "location": null,
              "status": "success",
              "error": null,
              "created_at": "2019-10-07T16:39:23+00:00",
              "updated_at": "2019-10-07T16:39:24+00:00"
            }
          },
          {
            "node": {
              "id": "5d9b6a3ba1361e00012268e8",
              "row": 2,
              "sku": "46401204",
              "quantity": 10,
              "action": "change",
              "reason": "Reason for changing inventory",
              "location": null,
              "status": "success",
              "error": null,
              "created_at": "2019-10-07T16:39:23+00:00",
              "updated_at": "2019-10-07T16:39:24+00:00"
            }
          },
          {
            "node": {
              "id": "5d9b6a3ba1361e00012268e8",
              "row": 3,
              "sku": "49071335",
              "quantity": 10,
              "action": "change",
              "reason": "Reason for changing inventory",
              "location": null,
              "status": "success",
              "error": null,
              "created_at": "2019-10-07T16:39:23+00:00",
              "updated_at": "2019-10-07T16:39:24+00:00"
            }
          },
          {
            "node": {
              "id": "5d9b6a3ba1361e00012268e8",
              "row": 4,
              "sku": "47028683",
              "quantity": 10,
              "action": "change",
              "reason": "Reason for changing inventory",
              "location": null,
              "status": "success",
              "error": null,
              "created_at": "2019-10-07T16:39:23+00:00",
              "updated_at": "2019-10-07T16:39:24+00:00"
            }
          },
          {
            "node": {
              "id": "5d9b6a3ba1361e00012268e8",
              "row": 5,
              "sku": "48061840",
              "quantity": 10,
              "action": "change",
              "reason": "Reason for changing inventory",
              "location": null,
              "status": "success",
              "error": null,
              "created_at": "2019-10-07T16:39:23+00:00",
              "updated_at": "2019-10-07T16:39:24+00:00"
            }
          }
        ]
      }
    }
  }
}

Inventory sync abort Mutation

This mutation allows you to abort a specific sync batch that was uploaded. Aborting a sync batch should be done before the batch is changed to a success status, and will not revert the lines already processed from the CSV file.

mutation {
  inventory_sync_abort(
    data: { sync_id: "5e4dac71b50fb5475c7b00d4", reason: "Wrong File" }
  ) {
    request_id
    complexity
    sync {
      id
      url
      user_id
      account_id
      warehouse_id
      customer_account_id
      total_count
      status
      error
      created_at
      updated_at
      success_count
      error_count
      finished_count
    }
  }
}

Inventory Snapshot

In this section, we will explore some examples of how we can use the Inventory snapshot.

Overview

A snapshot is just an asynchronous job that iterates over all warehouses that satisfy the criteria (owned or associated with a 3PL relationship), then iterates over all products in each warehouse that meet the criteria and aggregates vendors+bins+lots for each product, and throws all of that info into a big map of products to vendors, warehouses, and lots for each in JSON format.

When it finishes, it can send an email or post to an endpoint. This email or webhook will contain a link to the exported JSON file, which will be available for download for 24 hours.

To get either of the above, you must pass the notification_email or post_url fields respectively. Please ensure you are passing a valid email and/or endpoint URL that accepts POST messages.

We also offer a data export option that may be better suited for your needs. Reach out to support for more information.

Examples of how the snapshot should look like are:

Important

Requesting a full snapshot of all products from all warehouses is not recommended, and the request may not succeed for accounts with high SKU and warehouse counts.

To limit the size of the snapshot, use one of the following filters:

  • warehouse_id to get results for a specific warehouse.
  • customer_account_id to receive only SKUs for a specific customer account if you trigger the snapshot as a 3PL account.
  • has_inventory to return only SKUs that have stock.
  • updated_from to retrieve only SKUs that have been updated since the specified date-time (in UTC).

Inventory generate snapshot Mutation

In this example we will use the inventory_generate_snapshot Mutation, that allows us to generate a snapshot:

mutation {
  inventory_generate_snapshot(
    data: {
      warehouse_id: "V2FyZWhvuXNlOjEjUzkw"
      notification_email: "test@shiphero.com"
    }
  ) {
    request_id
    complexity
    snapshot {
      snapshot_id
      job_user_id
      job_account_id
      warehouse_id
      customer_account_id
      notification_email
      email_error
      post_url
      post_error
      post_url_pre_check
      status
      error
      created_at
      enqueued_at
      updated_at
      snapshot_url
      snapshot_expiration
    }
  }
}

And the response for it should be something like this:

{
  "data": {
    "inventory_generate_snapshot": {
      "request_id": "5e70d213fa462c9432d1a383",
      "complexity": 30,
      "snapshot": {
        "snapshot_id": "5e70d213ec6c5e62d4bf7170",
        "job_user_id": "VXNlcjo5MTIz",
        "job_account_id": "QWNjb3VudDo2MzM0",
        "warehouse_id": "V2FyZWhvuXNlOjEjUzkw",
        "customer_account_id": null,
        "notification_email": "test@shiphero.com",
        "email_error": null,
        "post_url": null,
        "post_error": null,
        "post_url_pre_check": true,
        "status": "enqueued",
        "error": null,
        "created_at": "2020-03-17T13:35:15+00:00",
        "enqueued_at": "2020-03-17T13:35:15.815864+00:00",
        "updated_at": "2020-03-17T13:35:15+00:00",
        "snapshot_url": null,
        "snapshot_expiration": null
      }
    }
  }
}

Inventory abort snapshot Mutation

If you would like to abort a snapshot that is being generated, you can use the inventory_abort_snapshot Mutation, that allows us to abort a specific snapshot, this is:

mutation {
  inventory_abort_snapshot(
    data: { snapshot_id: "5e94c048cec17923fcb7ec32", reason: "Wrong endpoint" }
  ) {
    request_id
    complexity
    snapshot {
      snapshot_id
      job_user_id
      job_account_id
      warehouse_id
      customer_account_id
      notification_email
      email_error
      post_url
      post_error
      post_url_pre_check
      status
      error
      created_at
      enqueued_at
      updated_at
      snapshot_url
      snapshot_expiration
    }
  }
}

Note

Snapshots can also be posted to a specific URL. In order to do this, you have to include two fields:

As for post_url_pre_check, if false, a pre-check on the POST URL will not be performed. This eliminates immediate validation and feedback in the mutation response, before sending the request to the worker. Nonetheless, disabling this check can be useful if a one-time token is used to authenticate the endpoint.

Inventory snapshot Query

This query allows us to get the status for a specific snapshot

query {
  inventory_snapshot(snapshot_id: "5e94c048cec17923fcb7ec32") {
    request_id
    complexity
    snapshot {
      snapshot_id
      job_user_id
      job_account_id
      warehouse_id
      customer_account_id
      notification_email
      email_error
      post_url
      post_error
      post_url_pre_check
      status
      error
      created_at
      enqueued_at
      updated_at
      snapshot_url
      snapshot_expiration
    }
  }
}

And the response should look something like this:

{
  "data": {
    "inventory_snapshot": {
      "request_id": "5e94c1d95dd8b16bf28392a9",
      "complexity": 1,
      "snapshot": {
        "snapshot_id": "5e94c048cec17923fcb7ec32",
        "job_user_id": "VXNlcjo5MTIz",
        "job_account_id": "QWNjb3VudDozODAx",
        "warehouse_id": "V2FyZWhvdXNlOjgwNzU=",
        "customer_account_id": null,
        "notification_email": "test@shiphero.com",
        "email_error": null,
        "post_url": null,
        "post_error": null,
        "post_url_pre_check": true,
        "status": "success",
        "error": null,
        "created_at": "2020-04-13T19:40:56+00:00",
        "enqueued_at": "2020-04-13T19:40:56.912000+00:00",
        "updated_at": "2020-04-13T19:40:57+00:00",
        "snapshot_url": "https://shiphero-uploads.s3.amazonaws.com/inventory_snapshots/3801/8075/Any/b24278f6-7dbe-11ea-9903-0af9fd70a979.json",
        "snapshot_expiration": null
      }
    }
  }
}

Inventory snapshots Query

This query allows us to get the status of all the snapshots for a specific warehouse or customer

query {
  inventory_snapshots(warehouse_id: "V2FyZWhvdXNlOjgwNzU=") {
    request_id
    complexity
    snapshots(first: 1) {
      edges {
        node {
          snapshot_id
          job_user_id
          job_account_id
          warehouse_id
          customer_account_id
          notification_email
          email_error
          post_url
          post_error
          post_url_pre_check
          status
          error
          created_at
          enqueued_at
          updated_at
          snapshot_url
          snapshot_expiration
        }
      }
    }
  }
}

And the response should look something like this:

{
  "data": {
    "inventory_snapshots": {
      "request_id": "5e94c0c401117d1e2b1a822c",
      "complexity": 11,
      "snapshots": {
        "edges": [
          {
            "node": {
              "snapshot_id": "5e94c048cec17923fcb7ec32",
              "job_user_id": "VXNlcjo5MTIz",
              "job_account_id": "QWNjb3VudDozODAx",
              "warehouse_id": "V2FyZWhvdXNlOjgwNzU=",
              "customer_account_id": null,
              "notification_email": "test@shiphero.com",
              "email_error": null,
              "post_url": null,
              "post_error": null,
              "post_url_pre_check": true,
              "status": "success",
              "error": null,
              "created_at": "2020-04-13T19:40:56+00:00",
              "enqueued_at": "2020-04-13T19:40:56.912000+00:00",
              "updated_at": "2020-04-13T19:40:57+00:00",
              "snapshot_url": "https://shiphero-uploads.s3.amazonaws.com/inventory_snapshots/3801/8075/Any/b24278f6-7dbe-11ea-9903-0af9fd70a979.json",
              "snapshot_expiration": null
            }
          }
        ]
      }
    }
  }
}