Skip to content
Need help with our api? Ask in Community
Inbound Shipments

Inbound Shipments

Inbound Shipments represent incoming inventory deliveries to a warehouse. You can use the Public API to create, update, list, and inspect inbound shipments, as well as retrieve photos and receiving summaries.

Note

Mutations in this section require the change:inbound_shipments OAuth scope. If your token is missing the view:pii scope, booking_contact_name, booking_contact_email, and booking_contact_number will be returned as null in responses rather than causing an error.

Create an Inbound Shipment

Use the inbound_shipment_create mutation to create a new inbound shipment. The only field required in every case is warehouse_id.

Note

You must provide either purchase_order_ids or vendor_id. If you omit purchase_order_ids, vendor_id becomes required — see Receiving on the fly below.

Below is an example using every field the mutation currently supports:

mutation {
  inbound_shipment_create(
    data: {
      customer_account_id: "QWNjb3VudDo2NzU="
      warehouse_id: "V2FyZWhvdXNlOjgwNzU="
      purchase_order_ids: ["UHVyY2hhc2VPcmRlcjoxMjM0NQ=="]
      vendor_id: "VmVuZG9yOjU1MTI="
      carrier: "FedEx Freight"
      pro_number: "PRO-12345"
      bol_reference: "BOL-98765"
      bol_url: "https://example.com/documents/bol-98765.pdf"
      expected_dock: "D12"
      dock_used: "D12"
      container_number: "CONT456789"
      notes: "Fragile items on pallet 3"
      estimated_truck_arrival: "2026-08-15T14:00:00Z"
      scheduled_at: "2026-08-15T14:00:00Z"
      truck_arrived_at: "2026-08-15T14:10:00Z"
      truck_unload_started_at: "2026-08-15T14:20:00Z"
      truck_unload_finished_at: "2026-08-15T16:00:00Z"
      truck_departure_at: "2026-08-15T16:15:00Z"
      booking_contact_name: "John Doe"
      booking_contact_email: "john@example.com"
      booking_contact_number: "555-123-4567"
      container_size: "s40ctr"
      load_type: "ftl"
      shipment_type: "pallet"
      number_carton: 10
      pallets_quantity: 4
      people_for_unload: 2
      people_for_receiving: 3
    }
  ) {
    request_id
    complexity
    inbound_shipment {
      id
      legacy_id
      status
      carrier
      pro_number
      bol_reference
      bol_url
      expected_dock
      dock_used
      container_number
      notes
      estimated_truck_arrival
      scheduled_at
      truck_arrived_at
      truck_unload_started_at
      truck_unload_finished_at
      truck_departure_at
      booking_contact_name
      booking_contact_email
      booking_contact_number
      container_size
      load_type
      shipment_type
      number_carton
      pallets_quantity
      people_for_unload
      people_for_receiving
      vendor_id
      warehouse {
        id
      }
      purchase_orders {
        edges {
          node {
            id
            po_number
          }
        }
      }
    }
  }
}

The shipment will be created with status PENDING_ARRIVAL (or ARRIVED if it’s created without a purchase order — see below).

Note

customer_account_id is only needed if you’re a 3PL performing this action on behalf of one of your customer accounts.

Note

Valid container_size values: s20ctr, s40ctr, s40hc, s45hc, s53_dry_van, box_truck, strait_truck, s48, reefer53, reefer48, dry_flatbed_pup, pup

Valid load_type values: ctn_carton, ltl, ftl, ctr

Valid shipment_type values: parcel, pallet, ctr_palletized, ctr_floor_loaded

Casing: send container_size, load_type, and shipment_type in lowercase (as shown above). They are returned in UPPERCASE on output (for example, load_type: FTL). This is expected behavior, not an error.

Field length limits: expected_dock and dock_used are limited to 8 characters, pro_number and bol_reference to 120 characters, bol_url to 500 characters, container_number to 25 characters, notes to 512 characters, booking_contact_name and booking_contact_email to 250 characters, and booking_contact_number to 45 characters.

Receiving on the fly (no purchase order)

If you don’t have a purchase order to attach yet, you can create an inbound shipment directly against a vendor instead of purchase_order_ids. ShipHero automatically creates an empty purchase order for that vendor and marks the shipment ARRIVED and unexpected:

mutation {
  inbound_shipment_create(
    data: {
      warehouse_id: "V2FyZWhvdXNlOjgwNzU="
      vendor_id: "VmVuZG9yOjU1MTI="
    }
  ) {
    request_id
    complexity
    inbound_shipment {
      id
      status
      vendor_id
    }
  }
}

Note

This call fails if receiving on the fly has been disabled for your account, or if neither purchase_order_ids nor vendor_id is provided.

Get a single Inbound Shipment

Use the inbound_shipment query to retrieve a single inbound shipment by its ID.

{
  inbound_shipment(id: "SW5ib3VuZFNoaXBtZW50OjEyMzQ=") {
    request_id
    complexity
    data {
      id
      legacy_id
      account_id
      warehouse_id
      status
      carrier
      pro_number
      bol_reference
      bol_url
      expected_dock
      dock_used
      container_number
      notes
      estimated_truck_arrival
      truck_arrived_at
      truck_unload_started_at
      truck_unload_finished_at
      truck_departure_at
      booking_contact_name
      booking_contact_email
      booking_contact_number
      container_size
      load_type
      shipment_type
      number_carton
      pallets_quantity
      people_for_unload
      people_for_receiving
      vendor_id
      created_at
      scheduled_at
      status_updated_at
      warehouse {
        id
        legacy_id
      }
      purchase_orders {
        edges {
          node {
            id
            po_number
          }
        }
      }
    }
  }
}

List Inbound Shipments

Use the inbound_shipments query to list inbound shipments with optional filters and cursor-based pagination.

{
  inbound_shipments(
    statuses: ["arrived", "receiving"]
    warehouse_ids: ["V2FyZWhvdXNlOjgwNzU="]
  ) {
    request_id
    complexity
    data(first: 10) {
      edges {
        node {
          id
          legacy_id
          account_id
          warehouse_id
          status
          carrier
          created_at
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}

You can filter by customer_ids, statuses, warehouse_ids, search_term, dates_from, dates_to, estimated_truck_arrival_from, estimated_truck_arrival_to, status_updated_at_from, status_updated_at_to, and require_fai.

Update an Inbound Shipment

Use the inbound_shipment_update mutation to update an existing inbound shipment.

Note

inbound_shipment_update supports a smaller set of fields than inbound_shipment_create. vendor_id, bol_reference, bol_url, expected_dock, dock_used, container_number, notes, scheduled_at, truck_unload_started_at, truck_unload_finished_at, truck_departure_at, people_for_unload, and people_for_receiving can only be set at creation time — they cannot be changed afterwards through the Public API.

mutation {
  inbound_shipment_update(
    data: {
      customer_account_id: "QWNjb3VudDo2NzU="
      inbound_shipment_id: "SW5ib3VuZFNoaXBtZW50OjEyMzQ="
      warehouse_id: "V2FyZWhvdXNlOjgwNzU="
      purchase_orders_ids: ["UHVyY2hhc2VPcmRlcjoxMjM0NQ=="]
      carrier: "UPS Freight"
      pro_number: "PRO-67890"
      estimated_truck_arrival: "2026-08-15T14:00:00Z"
      truck_arrived_at: "2026-08-15T14:10:00Z"
      booking_contact_name: "Jane Smith"
      booking_contact_email: "jane@example.com"
      booking_contact_number: "555-987-6543"
      container_size: "s20ctr"
      load_type: "ltl"
      shipment_type: "parcel"
      number_carton: 6
      pallets_quantity: 2
    }
  ) {
    request_id
    complexity
    inbound_shipment {
      id
      status
      carrier
      pro_number
      estimated_truck_arrival
      truck_arrived_at
      booking_contact_name
      booking_contact_email
      booking_contact_number
      container_size
      load_type
      shipment_type
      number_carton
      pallets_quantity
    }
  }
}

Note

The purchase_orders_ids field replaces the full list of associated purchase orders — it is the complete desired set, not a delta. If you want to keep existing POs, include them in the list along with any new ones. You cannot remove a purchase order once the shipment is ARRIVED or RECEIVING, and you cannot add one once it’s COMPLETED or DELETED.

As with inbound_shipment_create, container_size, load_type, and shipment_type are sent lowercase and returned uppercase.

Get Inbound Shipment Images

Use the inbound_shipment_images query to retrieve photos attached to an inbound shipment. Each image includes a signed URL for downloading the file.

{
  inbound_shipment_images(inbound_shipment_id: "SW5ib3VuZFNoaXBtZW50OjEyMzQ=") {
    data {
      url
      filename
      mimetype
      description
      inbound_shipment_line_item {
        id
        sku
        quantity
        quantity_received
        quantity_rejected
      }
      created_at
    }
  }
}

Get Inbound Shipment Summary

Use the inbound_shipment_summary query to get an LPN-based summary of what has been received into an inbound shipment. This shows received inventory grouped by pallet/box.

{
  inbound_shipment_summary(inbound_shipment_id: "SW5ib3VuZFNoaXBtZW50OjEyMzQ=") {
    data {
      stats {
        unpalletized_boxes_count
        pallets_count
      }
      in_lpns {
        lpn {
          id
          barcode
          container_type
        }
        quantity_received
        quantity_loose
        received_location {
          id
          location
          zone
        }
        content {
          product_info {
            sku
            name
          }
          lot {
            id
            name
            sku
          }
          quantity_received
          quantity_loose
          is_unexpected
          containers {
            lpn {
              id
              barcode
              container_type
            }
            quantity_received
          }
          receiving_location {
            id
            location
            zone
          }
          receiving_workers {
            id
            first_name
            last_name
          }
          inbound_shipment_line_item {
            id
            quantity
            quantity_received
            quantity_rejected
          }
        }
      }
    }
  }
}

Note

quantity_loose is inventory received but not yet placed into a container/pallet. containers lists any sub-containers (e.g. inner boxes on a pallet) holding this content. receiving_workers requires the view:pii scope — without it, this field returns null rather than an error.

You can optionally filter with only_owned_by_user, only_boxes_non_palletized, filter_by_location_id, lpn_id, and include_rejected.

Get Inbound Shipment Location Summary

Use the inbound_shipment_location_summary query to see where received inventory has been placed, grouped by warehouse location.

{
  inbound_shipment_location_summary(inbound_shipment_id: "SW5ib3VuZFNoaXBtZW50OjEyMzQ=") {
    data {
      locations {
        location {
          id
          location
          zone
        }
        items_at_location {
          product_info {
            sku
            name
          }
          lot {
            id
            name
            sku
          }
          eaches_quantity
          uom
          is_unexpected
          inbound_shipment_line_item {
            id
            quantity
            quantity_received
            quantity_rejected
          }
        }
      }
    }
  }
}

Note

uom indicates the unit of measure the quantity was recorded in at this location (for example, EACH or CASE), reflecting ShipHero’s unit-of-measure hierarchy for received inventory. lot is only populated for lot-tracked products. is_unexpected indicates the item wasn’t part of the original purchase order/ASN.