1. Manifests
  2. Manifests

Manifests

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.

Parameters

location_id string (required)
The ID of the location to which this manifest is being delivered.
articles array
An array of article objects representing the inventory items in the manifest. Each article supports item_id, sku, gtin, name, packed_qty, layout_id (bin to place inventory into on completion), special_handling_tags, assets, and quantity fields (verified_qty, damaged_qty, etc.).
containers array
An array of container (parcel) objects. Each container can include its own articles, a tracking_number, container_number, special_handling_tags, layout_id (bin to store the parcel or its contents), and unpacked (set to true to mark the parcel as opened and route its contents into layout_id).
order_number string
A custom order number for the manifest.
invoice_number string
The invoice number associated with the manifest.
purchase_order_number string
The purchase order number for the manifest.
reference_number string
A reference number for the manifest.
customer_purchase_order_number string
The customer purchase order number.
container_number string
The container number for the overall manifest.
load_number string
The load number for the manifest.
external_id string
An external identifier for the manifest.
alternate_external_id string
An alternate external identifier for the manifest.
special_handling_tags array
An array of special handling tags (e.g., ftl, lithium, frozen, hazmat, fragile).
arrived_at integer
The arrival timestamp in epoch seconds.
processed_at integer
The processing completion timestamp in epoch seconds.
estimated_delivery_at integer
The estimated delivery timestamp in epoch seconds.
tracking_number string
A tracking number for the manifest.
reason_code string
A reason code enum associated with the manifest.
metadata object
Key-value pairs of custom metadata.
sender object
Details about the contact sending the shipment.
recipient object
Details about the contact receiving the shipment.
shipment_info object
Details about the shipment being received, including provider_id, tracking_number, document_number.
attachments object
An object with add (array of attachment objects) and remove (array of attachment IDs) for managing attachments.
options object
Additional options for the manifest.
Options Details
verify_addresses boolean
Whether to validate sender and recipient addresses. Default: false
partial_completion string
Controls behavior when a manifest is partially completed. One of: close_partial, create_new, ask_user

Example - Receiving Inventory

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  articles: [
    {
      item_id: "item_pu8iNbturZy5zvB4zaUZ8t", //Create by ID
      packed_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.
      packed_qty: 50,
    },
    {
      gtin: "123456789", //Create by GTIN.
      packed_qty: 50,
    },
  ],
  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,
  },
  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;

      

The quantities in articles will also be reflected in the manifested_qty of the relevant item level, determined from the manifest's location and article's layout. If no layout is assigned to the article, the quantities will be reflected in the level created against the default layout of the location.

For example, for item item_pu8iNbturZy5zvB4zaUZ8t, Fetch the inventory levels of the article and check the manifested_qty

js
        let default_layout_id = "lay_" + manifest.location_id.split("_")[1];
const response = await fetch(`https://api.packagex.io/v1/items/item_pu8iNbturZy5zvB4zaUZ8t/levels`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const relevant_level = response.data.find((lvl) => lvl.location_id === manifest.location_id && lvl.layout_id === default_layout_id);
console.log(relevant_level.manifested_qty); // returns 50

      

Example - Receiving Parcels

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  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",
    },
  ],
  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,
  },
  recipient: {
    name: "Jamie Jones",
    email: "jamie@packagex.xyz",
    phone: "4844836699",
    address: "500 7th Ave, New York, NY 10018",
  },
}

      

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",
  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",
    },
  ],
  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",
      },
    ],
  },
};

      

For item manifests

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

  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

Assign Layout for Inventory Placement

You can specify a layout_id on articles and containers to control where inventory is placed when the manifest is completed.

On articles — the inventory for that article is received into the specified layout bin:

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  articles: [
    {
      item_id: "item_pu8iNbturZy5zvB4zaUZ8t",
      packed_qty: 10,
      layout_id: "lay_11cCoQQVr6BUKxRT9K1p4x", // receive into this bin
    },
  ],
};

      

On containers with unpacked: true — the parcel is marked as unpacked and its contents are placed into the specified layout bin:

js
        const data = {
  location_id: "loc_afnHMjVUn3gnrvxU5zMvkX",
  containers: [
    {
      id: "prcl_fpKJ7oiMyLPKhd8Ei6MyKX",
      unpacked: true,
      layout_id: "lay_11cCoQQVr6BUKxRT9K1p4x", // unpack contents into this bin
    },
  ],
};

      

After the update, parcel.unpacked will be true, parcel.layout.id will reflect the bin, and each item in parcel.contents will have its layout.id set accordingly.

If no layout_id is provided, inventory is placed into the level for the default layout of the manifest's location.

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: [
    {
      item_id: "item_pu8iNbturZy5zvB4zaUZ8t", //Create by ID
      packed_qty: 50,
    },
    {
      sku: "DRC123", //Create by SKU. If SKU doesn't exist we'll create one
      packed_qty: 50,
    },
    {
      gtin: "123456789", //Create by GTIN.
      packed_qty: 50,
    },
    {
      name: "Dispatch Roasters Coffee (3lb Bag)", //Will create a new item
      packed_qty: 50,
    },
  ],
  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,
        }
      ]
    }
  ]
};

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 article_1 = manifest.articles.find(art => art.id === "art_pu8iNbturZy5zvB4zaUZ8t")
console.log(article_1.received_qty) // returns 2
const article_2 = manifest.articles.find(art => art.id === "art_r3CnfTDe66HPNPZid2WVrr")
console.log(article_2.received_qty) // returns (old_received_qty + 10 - 1)
const article_3 = manifest.articles.find(art => art.id === "art_ubo3miFdD9v45ZZkhtY7Us")
console.log(article_3.received_qty) // returns 0

      

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 available_qty and damaged_qty properties updated in the relevant levels. These quantities are also subtracted from the manifested_qty.

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;

      

For item item_pu8iNbturZy5zvB4zaUZ8t, Fetch the inventory levels of the article and check the manifested_qty, verified_qty and defective_qty.

js
        let default_layout_id = "lay_" + manifest.location_id.split("_")[1];
const response = await fetch(`https://api.packagex.io/v1/items/item_pu8iNbturZy5zvB4zaUZ8t/levels`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const relevant_level = response.data.find((lvl) => lvl.location_id === manifest.location_id && lvl.layout_id === default_layout_id);
console.log(relevant_level.manifested_qty); // returns 48
console.log(relevant_level.available_qty); // returns old available_qty (if any) + 1
console.log(relevant_level.defective_qty); // returns old defective_qty (if any) + 1

      


Send Manifest Email

POST
`/v1/manifests/:manifest/email`

Sends a manifest summary email to the specified recipients. The email contains an order completion report (for completed manifests) or an order rejection report (for void manifests). The report includes item details such as name, SKU, packed quantities, verified quantities, defective quantities, and discrepancies.

WARNING

Emails can only be sent for manifests with a status of completed or void.

Parameters

recipients array (required)
An array of email addresses to send the manifest report to. Each entry must be a valid email address.

Example Request

js
        const data = {
  recipients: ["warehouse-manager@example.com", "operations@example.com"],
};

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

      

Send Manifest Parcel Email

POST
`/v1/manifests/:manifest/parcel-email`

Sends a parcel-level manifest summary email to the specified recipients. The email contains a per-parcel breakdown showing each parcel's ID, tracking number, and its received/defective/missing status. Like the manifest email, this works only for completed or void manifests.

WARNING

Emails can only be sent for manifests with a status of completed or void.

Parameters

recipients array (required)
An array of email addresses to send the parcel report to. Each entry must be a valid email address.

Example Request

js
        const data = {
  recipients: ["warehouse-manager@example.com", "receiving@example.com"],
};

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