1. Inventory
  2. Manifests

Inventory

Manifests

Before you create manifests, you'll want to set up locations in your dashboard so that you'll be able to add manifests to a certain location.

Create Manifest

POST
`/v1/manifests`

To create a manifest, you only need to include the location_id and specify the inventory items or parcels that you want to add. Parcel contents may be unknown, and may contain serialized inventory.

Example

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  articles: [
    {
      id: "item_pu8iNbturZy5zvB4zaUZ8t", //Create by ID
      manifested_qty: 50,
      assets: [
        {
          id: "ast_1Ab3133a4",
          manufacturer_number: "PX-PP-MOSDS-8",
        },
        {
          id: "ast_1Ab3133a5",
          manufacturer_number: "PX-PP-MOSDS-9",
        },
      ],
    },
    {
      sku: "DRC123", //Create by SKU. If SKU doesn't exist we'll create one
      manifested_qty: 50,
    },
    {
      gtin: "123456789", //Create by GTIN.
      manifested_qty: 50,
    },
    {
      name: "Dispatch Roasters Coffee (3lb Bag)", //Will create a new item
      manifested_qty: 50,
    },
  ],
  containers: [
    // parcels containing serialized or unserialized articles
    {
      container_id: "container_1",
      container_number: "CNTR-Pi31-001",
      tracking_number: "PKGX-0GP0241-UU22JNT",
    },
    {
      articles: [
        {
          item_id: "item_pu8iNbturZy5zvB4zaUZ8t",
          assets: [
            {
              id: "ast_1Ab3133a1",
              manufacturer_number: "PX-PP-MOSDS-3",
            },
            {
              id: "ast_1Ab3133a2",
              manufacturer_number: "PX-PP-MOSDS-4",
            },
          ],
        },
      ],
      container_id: "container_1",
      container_number: "CNTR-Pi31-001",
      tracking_number: "PKGX-0GOZRO1-URZ18CA",
    },
  ],
  shipment_options: {
    verify_addresses: false, // whether to verify addresses
  },
  sender: {
    name: "Little Nap Cafe",
    email: "jamie_jones.special@packagex.xyz",
    phone: "(484) 483-6699",
    address: "6951 Camino Degrazia, San Diego, CA 92111",
    address_line2: null,
  },
  // optional
  recipient: {
    name: "Jamie Jones",
    email: "jamie@packagex.xyz",
    phone: "4844836699",
    address: "500 7th Ave, New York, NY 10018",
  },
};

const response = await fetch("https://api.packagex.io/v1/manifests", {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
}).then((res) => res.json());

const manifest = response.data;

      

Attachments and Special Handling Tags

Special handling tags can be applied to articles, parcels or parcel contents. The manifest will reflect the unique set of special handling tags on all articles included in the manifest. Likewise, manifests allow you to add attachments. Attachments can be PDF files or images, both have to be base64 encoded.

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  shipment_options: {
    verify_addresses: false,
  },

  containers: [
    {
      special_handling_tags: ["lithium"],
      container_id: "container_1",
      container_number: "ASDF",
      tracking_number: "trk_123",
    },
    {
      special_handling_tags: ["lithium"],
      layout_id: "lay_11cCoQQVr6BUKxRT9K1p4x",
      articles: [
        {
          special_handling_tags: ["ftl"],
          item_id: "item_2z39qY36RthxqrJkJSpc52",
          is_asset: false,
          defective_qty: 2,
        },
      ],
      container_id: "container_2",
      container_number: "QWERT",
      tracking_number: "trk_0987",
    },
  ],
  articles: [
    {
      item_id: "item_2z39qY36RthxqrJkJSpc52",
      is_asset: false,
      layout_id: "lay_11cCoQQVr6BUKxRT9K1p4x",
      special_handling_tags: ["ftl"],
      assets: [
        {
          manufacturer_number: "PX-PP-MOSDS-1",
          defective: true,
        },
        {
          manufacturer_number: "PX-PP-MOSDS-2",
        },
      ],
    },
    {
      item_id: "item_2z39qY36RthxqrJkJSpc52",
      is_asset: false,
      layout_id: "lay_11cCoQQVr6BUKxRT9K1p4x",
      special_handling_tags: ["ftl"],
      assets: [
        {
          manufacturer_number: "PX-PP-MOSDS-1",
          defective: true,
        },
        {
          manufacturer_number: "PX-PP-MOSDS-2",
        },
      ],
    },
  ],
  shipment_info: {
    provider_id: "packagex",
    tracking_number: "PKGX-0GP09J1-U022414",
    document_number: "doc123",
    contact_email: "jamie@packagex.xyz",
  },
  recipient: {
    name: "Jamie Jones",
    email: "jamie@packagex.xyz",
    phone: "4844836699",
    address: "500 7th Ave, New York, NY 10018",
  },
  sender: {
    name: "Little Nap Cafe",
    email: "jamie_jones.special@packagex.xyz",
    phone: "(484) 483-6699",
    address: "6951 Camino Degrazia, San Diego, CA 92111",
    address_line2: null,
  },
  metadata: {
    key: "value",
  },
  attachments: {
    add: [
      {
        image:
          "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII",
        name: "Sample Attachment",
      },
    ],
  },
};

      

Active special handling tags must be enabled in the org settings. Only those special handling tags will be applied to the manifest that are enabled in the org settings. The list of available special handling tags are

  • ftl
  • ltl
  • lithium
  • frozen
  • chemicals
  • hazmat
  • perishable
  • oversize
  • fragile
  • dry_cleaning
  • alcohol
  • cannabis
  • confidential
  • marijuana
  • pharma
  • dry_ice

Enable tracking

Tracking can be enabled for manifests by providing relevant provider_id and tracking_number. For example, if you want to use PackageX trackers, do the following

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  articles: [
    {
      id: "item_pu8iNbturZy5zvB4zaUZ8t", //Create by ID
      manifested_qty: 50,
    },
    {
      sku: "DRC123", //Create by SKU. If SKU doesn't exist we'll create one
      manifested_qty: 50,
    },
    {
      gtin: "123456789", //Create by GTIN.
      manifested_qty: 50,
    },
    {
      name: "Dispatch Roasters Coffee (3lb Bag)", //Will create a new item
      manifested_qty: 50,
    },
  ],
  containers: [
    // parcels containing serialized or unserialized articles
    {
      articles: [
        {
          item_id: "item_pu8iNbturZy5zvB4zaUZ8t",
          assets: [
            {
              manufacturer_number: "PX-PP-MOSDS-1",
            },
            {
              manufacturer_number: "PX-PP-MOSDS-2",
            },
          ],
          requested_qty: 2,
        },
      ],
      container_id: "container_1",
      container_number: "ASDF",
      tracking_number: "trk_123",
    },
    {
      articles: [
        {
          item_id: "item_pu8iNbturZy5zvB4zaUZ8t",
          assets: [
            {
              id: "ast_1",
              manufacturer_number: "PX-PP-MOSDS-3",
            },
            {
              id: "ast_2",
              manufacturer_number: "PX-PP-MOSDS-4",
            },
          ],
        },
      ],
      container_id: "container_1",
      container_number: "ASDF",
      tracking_number: "trk_123",
    },
  ],
  shipment_options: {
    verify_addresses: false, // whether to verify addresses
  },
  sender: {
    name: "Little Nap Cafe",
    email: "jamie_jones.special@packagex.xyz",
    phone: "(484) 483-6699",
    address: "6951 Camino Degrazia, San Diego, CA 92111",
    address_line2: null,
  },
  shipment_info: {
    provider_id: "other",
    document_number: "doc123",
    tracking_number: "PKGX-0GP09J1-U022414",
  },
  // optional
  recipient: {
    name: "Jamie Jones",
    email: "jamie@packagex.xyz",
    phone: "4844836699",
    address: "500 7th Ave, New York, NY 10018",
  },
};

const response = await fetch("https://api.packagex.io/v1/manifests", {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
}).then((res) => res.json());

const manifest = response.data;
const tracker_id = response.data.tracker_id;

      

Update Manifest

POST
`/v1/manifests/:manifest`

Before you can update a manifest, you'll need to update its status to accepted. The reason this exists is because manifests can be created (with your permission) by third parties. Therefore, it's best that you accept them, and understand that there could be inventory items that will get created.

If you do not wish to proceed with the manifest, you can update the status to void instead.

Accept Manifest

js
        const data = {
  status: "accepted",
};

const response = await fetch(`https://api.packagex.io/v1/manifests/${manifest.id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
}).then((res) => res.json());

const manifest = response.data;

      

Mark Parcel as Defective, Missing or Received

Parcels can be marked as defective, missing or received by passing the relevant flag as true.

js
        const data = {
  containers: [
    id: "prcl_fpKJ7oiMyLPKhd8Ei6MyKX",
    defective: false,
    missing: false,
    received: true,
  ]
}

const response = await fetch(`https://api.packagex.io/v1/manifests/${manifest.id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
}).then((res) => res.json());

const manifest = response.data;
const updated_container = manifest.parcels.find(p => p.id == "prcl_fpKJ7oiMyLPKhd8Ei6MyKX")
updated_container.defective == false // true
updated_container.missing == false // true
updated_container.received == true // true

      

Verify Inventory

When verifying inventory for a manifest, we want to determine what is in good condition, bad condition, and what is missing. We do so by incrementing the verified_qty and damaged_qty properties on each inventory item or parcel content within the manifest.

js
        const data = {
  containers: [
    id: "prcl_fpKJ7oiMyLPKhd8Ei6MyKX"
    articles: [
      {
        id: "ctent_xrMpnxwxnXnWi1BRsvaL6q",
        verified_qty: 1,
        damaged_qty: 1,
      }
    ]
  ]
  articles: [
    {
      id: "art_pu8iNbturZy5zvB4zaUZ8t",
      verified_qty: 1,
      damaged_qty: 1,
    },
    {
      id: "art_r3CnfTDe66HPNPZid2WVrr",
      verified_qty: 10,
      damaged_qty: -1, //Remove one in case of a mistake, maybe like an undo button on the front end scanner app
    },
    {
      id: "art_ubo3miFdD9v45ZZkhtY7Us",
      verified_qty: [0], //Reset the value to zero, perhaps to start over
      damaged_qty: [0],
    },
  ],
};

const response = await fetch(`https://api.packagex.io/v1/manifests/${manifests.id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const manifest = response.data;

      

Adding to Inventory

When all items have been verified -- and even if some items are missing -- you are able to update the status of the manifest to 'completed'. Once this happens, all of the inventory items that are referenced in the manifest will automatically have their verified_qty and damaged_qty properties updated.

js
        const data = {
  status: "completed",
};

const response = await fetch(`https://api.packagex.io/v1/manifests/${manifest.id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
}).then((res) => res.json());

const manifest = response.data;

      

Retrieve Manifest

GET
`/v1/manifests/:manifest`

Get a single manifest using its id.

js
        const response = await fetch("https://api.packagex.io/v1/manifests/mfst_czhgjrk5JaVvyATPDbyURp", {
  method: "GET",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
}).then((res) => res.json());

const manifest = response.data;

      

List Manifests

Example

GET
`/v1/manifests`

When you want to retrieve multiple manifests, your data property on the result will always be an array even if you don't have any manifests.

js
        const response = await fetch("https://api.packagex.io/v1/manifests", {
  method: "GET",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
}).then((res) => res.json());

const manifests = response.data; //the array of items
const pagination = response.pagination; //the pagination object

      

Pagination

If the has_more property on the pagination object is set to true, you know there are more manifests in the database that have not been returned to you. The pagination object also has a page property indicating your current offset and a limit property. The total_count property in pagination returns the the total number of manifests in the database.

By default the page is set to 1 and the limit is 25.

If we want to query for items 26 - 50, we would request page 2 with a query parameter.

js
        const response = await fetch("https://api.packagex.io/v1/manifests?page=2&limit=25", {
  method: "GET",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
}).then((res) => res.json());

const manifests = response.data; //the array of items 25 - 50
const pagination = response.pagination; //the pagination object

      

Filter

You can filter manifests by location_id, statuses, value_added_services, updated_by, sender, recipient, special_handling_tags, provider_id.

You can also filter by date ranges on created_at, updated_at, arrived_at, and processed_at

  • location_id - Add the ID of one of your locations to get all of the deliveries currently mapped to that location. For example: location_id=loc_czhgjrk5JaVvyATPDbyURp
  • statuses - A comma separated list of manifest statuses. Keep in mind comma's in URLs are encoded as %2C, so we recommend using your platforms native URL encoding library. For example: statuses=processing,completed
  • updated_by - the key or id of the resource that last updated the manifest.
  • sender - contact id of the sender
  • recipient - contact id of the recipient
  • special_handling_tags - comma separated list of sepcial handling tags.
js
        const response = await fetch(
  "https://api.packagex.io/v1/manifests?location=loc_hj7gjrk5JaVvyATPDbyURp&statuses=processing%2Ccompleted",
  {
    method: "GET",
    headers: {
      "PX-API-KEY": process.env.PX_API_KEY,
      "Content-Type": "application/json",
    },
  }
).then((res) => res.json());

const manifests = response.data;
const pagination = response.pagination;

      

Sorting

Sorting describes in what order you want your responses to come in. You can select an available property by which to sort, as well as the direction.

  • order_by - The property by which to sort. Available properties are: created_at
  • direction - The direction to sort. Available directions are: asc and desc

By default, manifests will be sorted by in descending order, meaning the most recently created will be first.

js
        const response = await fetch("https://api.packagex.io/v1/manifests?order_by=created_at&direction=desc", {
  method: "GET",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
}).then((res) => res.json());

const manifests = response.data;
const pagination = response.pagination;

      

There are times when filtering is not enough and you want to find a specific manifest by some other attribute. In this case, you can do a fuzzy, typo-tolerant search. Below are the properties that are supported by our full text search.

Searchable Properties

  • order_number
  • tracking_number

To search, simply provide a string to search by using the search query param. The results will be order by the most relevant first. If you want to highlight matching search results for a frontend, we provide a special property for search-returned manifest objects called _search which will have the matched text surrounded with <mark> handles.

Ordering Search Results

By default, search results are ordered by relevance. However, if you include an order_by parameter along with your search query, the results will be ordered by the specified property instead of by relevance.

Relevance Score

Relevance scores are included in the search results by default. Note that this could add up to 10ms of extra time to the request.

js
        const response = await fetch("https://api.packagex.io/v1/manifests?search=123", {
  method: "GET",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
}).then((res) => res.json());

const manifest = response.data[0];